chore: merge main, resolve biome formatting conflicts

Merge origin/main into feat/document-file-conversion. Conflicts were
format-only (Tailwind class ordering, single-line vs multi-line) plus
two semantic merges:

- files.helpers.ts: combine main's pending-PDF download path with the
  branch's original-source-file (DOCX/PNG/JPEG) download path
- download-pdf.ts: combine main's versionToFilenameSuffix helper with
  the branch's server-provided Content-Disposition filename support
This commit is contained in:
ephraimduncan
2026-05-12 11:28:47 +00:00
1495 changed files with 22068 additions and 33465 deletions
+20 -10
View File
@@ -3,7 +3,7 @@ import type { EnvelopeItem } from '@prisma/client';
import { getEnvelopeItemPdfUrl } from '../utils/envelope-download';
import { downloadFile } from './download-file';
type DocumentVersion = 'original' | 'signed';
type DocumentVersion = 'original' | 'signed' | 'pending';
type DownloadPDFProps = {
envelopeItem: Pick<EnvelopeItem, 'id' | 'envelopeId'>;
@@ -14,12 +14,17 @@ type DownloadPDFProps = {
* Specifies which version of the document to download.
* 'signed': Downloads the signed version (default).
* 'original': Downloads the original version (may be DOCX, PNG, JPEG if converted).
* 'pending': Downloads the original document with currently-inserted fields burned in.
* Only valid while the envelope is in PENDING status. Not supported via
* recipient token.
*/
version?: DocumentVersion;
};
const getFilenameFromContentDisposition = (header: string | null): string | null => {
if (!header) return null;
if (!header) {
return null;
}
const filenameStarMatch = header.match(/filename\*=(?:UTF-8''|utf-8'')([^;]+)/i);
if (filenameStarMatch) {
@@ -39,12 +44,18 @@ const getFilenameFromContentDisposition = (header: string | null): string | null
return null;
};
export const downloadPDF = async ({
envelopeItem,
token,
fileName,
version = 'signed',
}: DownloadPDFProps) => {
const versionToFilenameSuffix = (version: DocumentVersion): string => {
switch (version) {
case 'signed':
return '_signed.pdf';
case 'pending':
return '_pending.pdf';
case 'original':
return '.pdf';
}
};
export const downloadPDF = async ({ envelopeItem, token, fileName, version = 'signed' }: DownloadPDFProps) => {
const downloadUrl = getEnvelopeItemPdfUrl({
type: 'download',
envelopeItem: envelopeItem,
@@ -63,8 +74,7 @@ export const downloadPDF = async ({
filename = serverFilename;
} else {
const baseTitle = (fileName ?? 'document').replace(/\.[^/.]+$/, '');
const suffix = version === 'signed' ? '_signed.pdf' : '.pdf';
filename = `${baseTitle}${suffix}`;
filename = `${baseTitle}${versionToFilenameSuffix(version)}`;
}
downloadFile({
@@ -1,7 +1,15 @@
import { posthog } from 'posthog-js';
import { extractPostHogConfig } from '@documenso/lib/constants/feature-flags';
let posthogPromise: Promise<typeof import('posthog-js')> | null = null;
const getPosthog = async () => {
if (!posthogPromise) {
posthogPromise = import('posthog-js');
}
return posthogPromise;
};
export function useAnalytics() {
// const featureFlags = useFeatureFlags();
const isPostHogEnabled = extractPostHogConfig();
@@ -17,7 +25,9 @@ export function useAnalytics() {
return;
}
posthog.capture(event, properties);
void getPosthog().then(({ default: posthog }) => {
posthog.capture(event, properties);
});
};
/**
@@ -31,7 +41,9 @@ export function useAnalytics() {
return;
}
posthog.captureException(error, properties);
void getPosthog().then(({ default: posthog }) => {
posthog.captureException(error, properties);
});
};
/**
@@ -5,10 +5,7 @@ type SaveRequest<T, R> = {
onResponse?: (response: R) => void;
};
export const useAutoSave = <T, R = void>(
onSave: (data: T) => Promise<R>,
options: { delay?: number } = {},
) => {
export const useAutoSave = <T, R = void>(onSave: (data: T) => Promise<R>, options: { delay?: number } = {}) => {
const { delay = 2000 } = options;
const saveTimeoutRef = useRef<NodeJS.Timeout>();
@@ -11,8 +11,7 @@ export type UseCopyShareLinkOptions = {
export function useCopyShareLink({ onSuccess, onError }: UseCopyShareLinkOptions) {
const [, copyToClipboard] = useCopyToClipboard();
const { mutateAsync: createOrGetShareLink, isPending: isCreatingShareLink } =
trpc.document.share.useMutation();
const { mutateAsync: createOrGetShareLink, isPending: isCreatingShareLink } = trpc.document.share.useMutation();
/**
* Copy a newly created, or pre-existing share link to the user's clipboard.
@@ -18,9 +18,7 @@ export function useCopyToClipboard(): [CopiedValue, CopyFn] {
// Try to save to clipboard then save it in the state if worked
try {
isClipboardApiSupported
? await handleClipboardApiCopy(text, blobType)
: await handleWriteTextCopy(text);
isClipboardApiSupported ? await handleClipboardApiCopy(text, blobType) : await handleWriteTextCopy(text);
setCopiedText(await text);
return true;
@@ -1,6 +1,5 @@
import { useCallback } from 'react';
import { getBoundingClientRect } from '@documenso/lib/client-only/get-bounding-client-rect';
import { useCallback } from 'react';
export const useDocumentElement = () => {
/**
@@ -15,9 +14,7 @@ export const useDocumentElement = () => {
const $page =
target.closest<HTMLElement>(pageSelector) ??
document
.elementsFromPoint(event.clientX, event.clientY)
.find((el) => el.matches(pageSelector));
document.elementsFromPoint(event.clientX, event.clientY).find((el) => el.matches(pageSelector));
if (!$page) {
return null;
@@ -31,19 +28,9 @@ export const useDocumentElement = () => {
* as a percentage of the page width and height.
*/
const getFieldPosition = (page: HTMLElement, field: HTMLElement) => {
const {
top: pageTop,
left: pageLeft,
height: pageHeight,
width: pageWidth,
} = getBoundingClientRect(page);
const { top: pageTop, left: pageLeft, height: pageHeight, width: pageWidth } = getBoundingClientRect(page);
const {
top: fieldTop,
left: fieldLeft,
height: fieldHeight,
width: fieldWidth,
} = getBoundingClientRect(field);
const { top: fieldTop, left: fieldLeft, height: fieldHeight, width: fieldWidth } = getBoundingClientRect(field);
return {
x: ((fieldLeft - pageLeft) / pageWidth) * 100,
@@ -60,31 +47,28 @@ export const useDocumentElement = () => {
* @param mouseWidth The artifical width of the mouse.
* @param mouseHeight The artifical height of the mouse.
*/
const isWithinPageBounds = useCallback(
(event: MouseEvent, pageSelector: string, mouseWidth = 0, mouseHeight = 0) => {
const $page = getPage(event, pageSelector);
const isWithinPageBounds = useCallback((event: MouseEvent, pageSelector: string, mouseWidth = 0, mouseHeight = 0) => {
const $page = getPage(event, pageSelector);
if (!$page) {
return false;
}
if (!$page) {
return false;
}
const { top, left, height, width } = $page.getBoundingClientRect();
const { top, left, height, width } = $page.getBoundingClientRect();
const halfMouseWidth = mouseWidth / 2;
const halfMouseHeight = mouseHeight / 2;
const halfMouseWidth = mouseWidth / 2;
const halfMouseHeight = mouseHeight / 2;
if (event.clientY > top + height - halfMouseHeight || event.clientY < top + halfMouseHeight) {
return false;
}
if (event.clientY > top + height - halfMouseHeight || event.clientY < top + halfMouseHeight) {
return false;
}
if (event.clientX > left + width - halfMouseWidth || event.clientX < left + halfMouseWidth) {
return false;
}
if (event.clientX > left + width - halfMouseWidth || event.clientX < left + halfMouseWidth) {
return false;
}
return true;
},
[],
);
return true;
}, []);
return {
getPage,
@@ -1,15 +1,13 @@
import { useCallback, useEffect, useMemo, useState } from 'react';
import { zodResolver } from '@hookform/resolvers/zod';
import type { Field } from '@prisma/client';
import { FieldType } from '@prisma/client';
import { useFieldArray, useForm } from 'react-hook-form';
import { z } from 'zod';
import { getPdfPagesCount } from '@documenso/lib/constants/pdf-viewer';
import type { TEditorEnvelope } from '@documenso/lib/types/envelope-editor';
import { ZFieldMetaSchema } from '@documenso/lib/types/field-meta';
import { nanoid } from '@documenso/lib/universal/id';
import { zodResolver } from '@hookform/resolvers/zod';
import type { Field } from '@prisma/client';
import { FieldType } from '@prisma/client';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useFieldArray, useForm } from 'react-hook-form';
import { z } from 'zod';
export const ZLocalFieldSchema = z.object({
// This is the actual ID of the field if created.
@@ -67,10 +65,7 @@ type UseEditorFieldsResponse = {
resetForm: (fields?: Field[]) => void;
};
export const useEditorFields = ({
envelope,
handleFieldsUpdate,
}: EditorFieldsProps): UseEditorFieldsResponse => {
export const useEditorFields = ({ envelope, handleFieldsUpdate }: EditorFieldsProps): UseEditorFieldsResponse => {
const [selectedFieldFormId, setSelectedFieldFormId] = useState<string | null>(null);
const [selectedRecipientId, setSelectedRecipientId] = useState<number | null>(null);
@@ -123,9 +118,7 @@ export const useEditorFields = ({
}
const foundField = localFields.find((field) => field.formId === formId);
const recipient = envelope.recipients.find(
(recipient) => recipient.id === foundField?.recipientId,
);
const recipient = envelope.recipients.find((recipient) => recipient.id === foundField?.recipientId);
if (recipient) {
setSelectedRecipient(recipient.id);
@@ -319,9 +312,7 @@ export const useEditorFields = ({
};
};
const restrictFieldPosValues = (
field: Pick<TLocalField, 'positionX' | 'positionY' | 'width' | 'height'>,
) => {
const restrictFieldPosValues = (field: Pick<TLocalField, 'positionX' | 'positionY' | 'width' | 'height'>) => {
return {
positionX: Math.max(0, Math.min(100, field.positionX)),
positionY: Math.max(0, Math.min(100, field.positionY)),
@@ -1,19 +1,14 @@
import { useId } from 'react';
import { ZRecipientActionAuthTypesSchema, ZRecipientAuthOptionsSchema } from '@documenso/lib/types/document-auth';
import type { TEditorEnvelope } from '@documenso/lib/types/envelope-editor';
import { ZRecipientEmailSchema } from '@documenso/lib/types/recipient';
import { zodResolver } from '@hookform/resolvers/zod';
import { DocumentSigningOrder, RecipientRole } from '@prisma/client';
import { useId } from 'react';
import type { UseFormReturn } from 'react-hook-form';
import { useForm } from 'react-hook-form';
import { prop, sortBy } from 'remeda';
import { z } from 'zod';
import {
ZRecipientActionAuthTypesSchema,
ZRecipientAuthOptionsSchema,
} from '@documenso/lib/types/document-auth';
import type { TEditorEnvelope } from '@documenso/lib/types/envelope-editor';
import { ZRecipientEmailSchema } from '@documenso/lib/types/recipient';
const LocalRecipientSchema = z.object({
formId: z.string().min(1),
id: z.number().optional(),
@@ -48,9 +43,7 @@ type UseEditorRecipientsResponse = {
resetForm: (options?: ResetFormOptions) => void;
};
export const useEditorRecipients = ({
envelope,
}: EditorRecipientsProps): UseEditorRecipientsResponse => {
export const useEditorRecipients = ({ envelope }: EditorRecipientsProps): UseEditorRecipientsResponse => {
const initialId = useId();
const generateDefaultValues = (options?: ResetFormOptions) => {
@@ -83,8 +76,7 @@ export const useEditorRecipients = ({
return {
signers,
signingOrder: documentMeta?.signingOrder ?? envelope.documentMeta.signingOrder,
allowDictateNextSigner:
documentMeta?.allowDictateNextSigner ?? envelope.documentMeta.allowDictateNextSigner,
allowDictateNextSigner: documentMeta?.allowDictateNextSigner ?? envelope.documentMeta.allowDictateNextSigner,
};
};
@@ -1,6 +1,5 @@
import { useCallback, useEffect, useState } from 'react';
import { getBoundingClientRect } from '@documenso/lib/client-only/get-bounding-client-rect';
import { useCallback, useEffect, useState } from 'react';
export const useElementBounds = (elementOrSelector: HTMLElement | string, withScroll = false) => {
const [bounds, setBounds] = useState({
@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/consistent-type-assertions */
import { RefObject, useEffect, useState } from 'react';
import { useEffect, useState } from 'react';
/**
* Calculate the width and height of a text element.
@@ -15,7 +15,9 @@ export function useEnvelopeAutosave<T>(saveFn: (data: T) => Promise<void>, delay
// A debounce or promise means something is pending
setIsPending(true);
if (timeoutRef.current) clearTimeout(timeoutRef.current);
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}
// eslint-disable-next-line @typescript-eslint/no-misused-promises
timeoutRef.current = setTimeout(async () => {
@@ -1,16 +1,9 @@
import { getBoundingClientRect } from '@documenso/lib/client-only/get-bounding-client-rect';
import { PDF_VIEWER_CONTENT_SELECTOR, PDF_VIEWER_PAGE_SELECTOR } from '@documenso/lib/constants/pdf-viewer';
import type { Field } from '@prisma/client';
import { useCallback, useEffect, useState } from 'react';
import type { Field } from '@prisma/client';
import { getBoundingClientRect } from '@documenso/lib/client-only/get-bounding-client-rect';
import {
PDF_VIEWER_CONTENT_SELECTOR,
PDF_VIEWER_PAGE_SELECTOR,
} from '@documenso/lib/constants/pdf-viewer';
export const useFieldPageCoords = (
field: Pick<Field, 'positionX' | 'positionY' | 'width' | 'height' | 'page'>,
) => {
export const useFieldPageCoords = (field: Pick<Field, 'positionX' | 'positionY' | 'width' | 'height' | 'page'>) => {
const [coords, setCoords] = useState({
x: 0,
y: 0,
@@ -19,9 +12,7 @@ export const useFieldPageCoords = (
});
const calculateCoords = useCallback(() => {
const $page = document.querySelector<HTMLElement>(
`${PDF_VIEWER_PAGE_SELECTOR}[data-page-number="${field.page}"]`,
);
const $page = document.querySelector<HTMLElement>(`${PDF_VIEWER_PAGE_SELECTOR}[data-page-number="${field.page}"]`);
if (!$page) {
return;
@@ -1,10 +1,6 @@
import { PDF_VIEWER_CONTENT_SELECTOR, PDF_VIEWER_PAGE_SELECTOR } from '@documenso/lib/constants/pdf-viewer';
import { useEffect, useState } from 'react';
import {
PDF_VIEWER_CONTENT_SELECTOR,
PDF_VIEWER_PAGE_SELECTOR,
} from '@documenso/lib/constants/pdf-viewer';
/**
* Returns whether the PDF page element for the given page number is currently
* present in the DOM. With virtual list rendering only pages near the viewport
@@ -1,8 +1,7 @@
import Konva from 'konva';
import { useEffect, useMemo, useRef } from 'react';
import Konva from 'konva';
import { type PageRenderData } from '../providers/envelope-render-provider';
import type { PageRenderData } from '../providers/envelope-render-provider';
type RenderFunction = (props: { stage: Konva.Stage; pageLayer: Konva.Layer }) => void;
@@ -66,7 +65,7 @@ export const usePageRenderer = (renderFunction: RenderFunction, pageData: PageRe
pageLayer: pageLayer.current,
});
void document.fonts.ready.then(function () {
void document.fonts.ready.then(() => {
pageLayer.current?.batchDraw();
});
@@ -1,5 +1,5 @@
import * as React from 'react';
import type { Dispatch, SetStateAction } from 'react';
import * as React from 'react';
function dispatchStorageEvent(key: string, newValue: string | null) {
window.dispatchEvent(new StorageEvent('storage', { key, newValue }));
@@ -25,20 +25,13 @@ const useSessionStorageSubscribe = (callback: (event: StorageEvent) => void) =>
return () => window.removeEventListener('storage', callback);
};
export function useSessionStorage<T>(
key: string,
initialValue: T,
): [T, Dispatch<SetStateAction<T>>] {
export function useSessionStorage<T>(key: string, initialValue: T): [T, Dispatch<SetStateAction<T>>] {
const serializedInitialValue = JSON.stringify(initialValue);
const getSnapshot = () => getSessionStorageItem(key);
const getServerSnapshot = () => serializedInitialValue;
const store = React.useSyncExternalStore(
useSessionStorageSubscribe,
getSnapshot,
getServerSnapshot,
);
const store = React.useSyncExternalStore(useSessionStorageSubscribe, getSnapshot, getServerSnapshot);
const setState: Dispatch<SetStateAction<T>> = React.useCallback(
(v) => {
@@ -1,9 +1,3 @@
import React, { createContext, useCallback, useContext, useMemo, useRef, useState } from 'react';
import { useLingui } from '@lingui/react/macro';
import { EnvelopeType, Prisma, ReadStatus, SendStatus, SigningStatus } from '@prisma/client';
import { useSearchParams } from 'react-router';
import { DO_NOT_INVALIDATE_QUERY_ON_MUTATION } from '@documenso/lib/constants/trpc';
import {
DEFAULT_EDITOR_CONFIG,
@@ -17,11 +11,16 @@ import type { TUpdateEnvelopeRequest } from '@documenso/trpc/server/envelope-rou
import type { TRecipientColor } from '@documenso/ui/lib/recipient-colors';
import { getRecipientColor } from '@documenso/ui/lib/recipient-colors';
import { useToast } from '@documenso/ui/primitives/use-toast';
import { useLingui } from '@lingui/react/macro';
import { EnvelopeType, Prisma, ReadStatus, SendStatus, SigningStatus } from '@prisma/client';
import type React from 'react';
import { createContext, useCallback, useContext, useMemo, useRef, useState } from 'react';
import { useSearchParams } from 'react-router';
import type { TDocumentEmailSettings } from '../../types/document-email';
import { formatDocumentsPath, formatTemplatesPath } from '../../utils/teams';
import { useEditorFields } from '../hooks/use-editor-fields';
import type { TLocalField } from '../hooks/use-editor-fields';
import { useEditorFields } from '../hooks/use-editor-fields';
import { useEditorRecipients } from '../hooks/use-editor-recipients';
import { useEnvelopeAutosave } from '../hooks/use-envelope-autosave';
@@ -176,16 +175,12 @@ export const EnvelopeEditorProvider = ({
setEnvelope((prev) => ({
...prev,
recipients,
fields: prev.fields.filter((field) =>
recipients.some((recipient) => recipient.id === field.recipientId),
),
fields: prev.fields.filter((field) => recipients.some((recipient) => recipient.id === field.recipientId)),
}));
// Reset the local fields to ensure deleted recipient fields are removed.
editorFields.resetForm(
envelope.fields.filter((field) =>
recipients.some((recipient) => recipient.id === field.recipientId),
),
envelope.fields.filter((field) => recipients.some((recipient) => recipient.id === field.recipientId)),
);
setAutosaveError(false);
@@ -203,9 +198,7 @@ export const EnvelopeEditorProvider = ({
}
}, 1000);
const setRecipientsAsync = async (
localRecipients: TSetEnvelopeRecipientsRequest['recipients'],
) => {
const setRecipientsAsync = async (localRecipients: TSetEnvelopeRecipientsRequest['recipients']) => {
setRecipientsDebounced(localRecipients);
await flushSetRecipients();
};
@@ -346,8 +339,7 @@ export const EnvelopeEditorProvider = ({
};
const getRecipientColorKey = useCallback(
(recipientId: number) =>
getRecipientColor(envelope.recipients.findIndex((r) => r.id === recipientId)),
(recipientId: number) => getRecipientColor(envelope.recipients.findIndex((r) => r.id === recipientId)),
[envelope.recipients],
);
@@ -536,10 +528,7 @@ const mapLocalRecipientsToRecipients = ({
documentDeletedAt: foundRecipient?.documentDeletedAt || null,
expired: foundRecipient?.expired || null,
signedAt: foundRecipient?.signedAt || null,
authOptions:
recipient.actionAuth.length > 0
? { actionAuth: recipient.actionAuth, accessAuth: [] }
: null,
authOptions: recipient.actionAuth.length > 0 ? { actionAuth: recipient.actionAuth, accessAuth: [] } : null,
signingOrder: recipient.signingOrder ?? null,
rejectionReason: foundRecipient?.rejectionReason || null,
role: recipient.role,
@@ -1,16 +1,26 @@
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
import React from 'react';
import { type Field, type Recipient } from '@prisma/client';
import type { DocumentDataVersion } from '@documenso/lib/types/document';
import { getDocumentDataUrl } from '@documenso/lib/utils/envelope-download';
import type { TRecipientColor } from '@documenso/ui/lib/recipient-colors';
import { getRecipientColor } from '@documenso/ui/lib/recipient-colors';
import type { Field, Recipient } from '@prisma/client';
import type React from 'react';
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
import type { TEnvelope } from '../../types/envelope';
import type { FieldRenderMode } from '../../universal/field-renderer/render-field';
/**
* The signature data for an inserted signature field.
*
* Loaded separately from the envelope to avoid bloating the envelope.get response
* with potentially large base64 image payloads.
*/
export type EnvelopeRenderFieldSignature = {
fieldId: number;
signatureImageAsBase64: string | null;
typedSignature: string | null;
};
export type PageRenderData = {
scale: number;
pageIndex: number;
@@ -50,6 +60,7 @@ type EnvelopeRenderProviderValue = {
currentEnvelopeItem: EnvelopeRenderItem | null;
setCurrentEnvelopeItem: (envelopeItemId: string) => void;
fields: Field[];
signatures: EnvelopeRenderFieldSignature[];
recipients: Pick<Recipient, 'id' | 'name' | 'email' | 'signingStatus'>[];
getRecipientColorKey: (recipientId: number) => TRecipientColor;
@@ -89,6 +100,15 @@ interface EnvelopeRenderProviderProps {
*/
fields?: Field[];
/**
* Optional inserted signature data for signature fields.
*
* Fetched separately from the envelope to keep the envelope response lean.
* If a signature field has no entry here, the renderer will fall back to
* showing the field type placeholder.
*/
signatures?: EnvelopeRenderFieldSignature[];
/**
* Optional recipient used to determine the color of the fields and hover
* previews.
@@ -137,6 +157,7 @@ export const EnvelopeRenderProvider = ({
envelope,
envelopeItems: envelopeItemsFromProps,
fields,
signatures,
token,
presignToken,
recipients = [],
@@ -192,10 +213,7 @@ export const EnvelopeRenderProvider = ({
}
}, [currentItem, envelopeItems]);
const recipientIds = useMemo(
() => recipients.map((recipient) => recipient.id).sort(),
[recipients],
);
const recipientIds = useMemo(() => recipients.map((recipient) => recipient.id).sort(), [recipients]);
const getRecipientColorKey = useCallback(
(recipientId: number) => getRecipientColor(recipientIds.findIndex((id) => id === recipientId)),
@@ -212,6 +230,7 @@ export const EnvelopeRenderProvider = ({
currentEnvelopeItem: currentItem,
setCurrentEnvelopeItem,
fields: fields ?? [],
signatures: signatures ?? [],
recipients,
getRecipientColorKey,
renderError,
@@ -1,11 +1,7 @@
import type { I18n, Messages } from '@lingui/core';
import { setupI18n } from '@lingui/core';
import {
APP_I18N_OPTIONS,
SUPPORTED_LANGUAGE_CODES,
isValidLanguageCode,
} from '../../constants/i18n';
import { APP_I18N_OPTIONS, isValidLanguageCode, SUPPORTED_LANGUAGE_CODES } from '../../constants/i18n';
import { env } from '../../utils/env';
import { remember } from '../../utils/remember';
@@ -1,7 +1,6 @@
import { useState } from 'react';
import { type Messages, setupI18n } from '@lingui/core';
import { I18nProvider } from '@lingui/react';
import { useState } from 'react';
import type { I18nLocaleData } from '../../constants/i18n';
@@ -1,7 +1,6 @@
import { createContext, useContext } from 'react';
import React from 'react';
import type { OrganisationSession } from '@documenso/trpc/server/organisation-router/get-organisation-session.types';
import type React from 'react';
import { createContext, useContext } from 'react';
type OrganisationProviderValue = OrganisationSession;
@@ -27,7 +26,5 @@ export const useOptionalCurrentOrganisation = () => {
};
export const OrganisationProvider = ({ children, organisation }: OrganisationProviderProps) => {
return (
<OrganisationContext.Provider value={organisation}>{children}</OrganisationContext.Provider>
);
return <OrganisationContext.Provider value={organisation}>{children}</OrganisationContext.Provider>;
};
@@ -1,13 +1,11 @@
import { createContext, useCallback, useContext, useEffect, useState } from 'react';
import React from 'react';
import type { Session } from '@prisma/client';
import { useLocation } from 'react-router';
import { authClient } from '@documenso/auth/client';
import type { SessionUser } from '@documenso/auth/server/lib/session/session';
import { trpc } from '@documenso/trpc/client';
import type { TGetOrganisationSessionResponse } from '@documenso/trpc/server/organisation-router/get-organisation-session.types';
import type { Session } from '@prisma/client';
import type React from 'react';
import { createContext, useCallback, useContext, useEffect, useState } from 'react';
import { useLocation } from 'react-router';
import { SKIP_QUERY_BATCH_META } from '../../constants/trpc';
@@ -74,8 +72,7 @@ export const SessionProvider = ({ children, initialSession }: SessionProviderPro
.catch((e) => {
const errorMessage = typeof e.message === 'string' ? e.message.toLowerCase() : '';
const isNetworkError =
errorMessage.includes('networkerror') || errorMessage.includes('failed to fetch');
const isNetworkError = errorMessage.includes('networkerror') || errorMessage.includes('failed to fetch');
// If the error is a transient network/abort error (e.g. page refresh while
// fetch was in-flight), return null to signal we should skip the state update.
+2 -11
View File
@@ -1,11 +1,5 @@
import type { Recipient } from '@prisma/client';
import {
DocumentDistributionMethod,
ReadStatus,
RecipientRole,
SendStatus,
SigningStatus,
} from '@prisma/client';
import { DocumentDistributionMethod, ReadStatus, RecipientRole, SendStatus, SigningStatus } from '@prisma/client';
type RecipientForType = Pick<Recipient, 'role' | 'signingStatus' | 'readStatus' | 'sendStatus'>;
@@ -29,10 +23,7 @@ export const getRecipientType = (
return RecipientStatusType.REJECTED;
}
if (
recipient.readStatus === ReadStatus.OPENED &&
recipient.signingStatus === SigningStatus.NOT_SIGNED
) {
if (recipient.readStatus === ReadStatus.OPENED && recipient.signingStatus === SigningStatus.NOT_SIGNED) {
return RecipientStatusType.OPENED;
}