mirror of
https://github.com/documenso/documenso.git
synced 2025-11-19 19:21:39 +10:00
Merge branch 'main' into feat/passkey
This commit is contained in:
27
packages/app-tests/e2e/test-delete-user.spec.ts
Normal file
27
packages/app-tests/e2e/test-delete-user.spec.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { expect, test } from '@playwright/test';
|
||||
|
||||
import { WEBAPP_BASE_URL } from '@documenso/lib/constants/app';
|
||||
import { getUserByEmail } from '@documenso/lib/server-only/user/get-user-by-email';
|
||||
import { seedUser } from '@documenso/prisma/seed/users';
|
||||
|
||||
import { manualLogin } from './fixtures/authentication';
|
||||
|
||||
test('delete user', async ({ page }) => {
|
||||
const user = await seedUser();
|
||||
|
||||
await manualLogin({
|
||||
page,
|
||||
email: user.email,
|
||||
redirectPath: '/settings',
|
||||
});
|
||||
|
||||
await page.getByRole('button', { name: 'Delete Account' }).click();
|
||||
await page.getByLabel('Confirm Email').fill(user.email);
|
||||
await expect(page.getByRole('button', { name: 'Confirm Deletion' })).not.toBeDisabled();
|
||||
await page.getByRole('button', { name: 'Confirm Deletion' }).click();
|
||||
|
||||
await page.waitForURL(`${WEBAPP_BASE_URL}/signin`);
|
||||
|
||||
// Verify that the user no longer exists in the database
|
||||
await expect(getUserByEmail({ email: user.email })).rejects.toThrow();
|
||||
});
|
||||
@ -20,7 +20,7 @@ module.exports = {
|
||||
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: ['../../apps/*/tsconfig.json', '../../packages/*/tsconfig.json'],
|
||||
project: ['../../tsconfig.eslint.json'],
|
||||
ecmaVersion: 2022,
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
export const URL_REGEX =
|
||||
/^(https?):\/\/(?:www\.)?[a-zA-Z0-9-]+\.[a-zA-Z0-9()]{2,}(?:\/[a-zA-Z0-9-._?&=/]*)?$/i;
|
||||
/^(https?):\/\/(?:www\.)?(?:[a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.[a-zA-Z0-9()]{2,}(?:\/[a-zA-Z0-9-._?&=/]*)?$/i;
|
||||
|
||||
@ -37,6 +37,12 @@ export const findTemplates = async ({
|
||||
where: whereFilter,
|
||||
include: {
|
||||
templateDocumentData: true,
|
||||
team: {
|
||||
select: {
|
||||
id: true,
|
||||
url: true,
|
||||
},
|
||||
},
|
||||
Field: true,
|
||||
Recipient: true,
|
||||
},
|
||||
|
||||
@ -10,9 +10,10 @@
|
||||
"clean": "rimraf node_modules",
|
||||
"post-install": "prisma generate",
|
||||
"prisma:generate": "prisma generate",
|
||||
"prisma:migrate-dev": "prisma migrate dev",
|
||||
"prisma:migrate-dev": "prisma migrate dev --skip-seed",
|
||||
"prisma:migrate-deploy": "prisma migrate deploy",
|
||||
"prisma:seed": "prisma db seed"
|
||||
"prisma:seed": "prisma db seed",
|
||||
"prisma:studio": "prisma studio"
|
||||
},
|
||||
"prisma": {
|
||||
"seed": "ts-node --transpileOnly --project ./tsconfig.seed.json ./seed-database.ts"
|
||||
|
||||
@ -28,6 +28,9 @@ module.exports = {
|
||||
DEFAULT: 'hsl(var(--secondary))',
|
||||
foreground: 'hsl(var(--secondary-foreground))',
|
||||
},
|
||||
warning: {
|
||||
DEFAULT: 'hsl(var(--warning))',
|
||||
},
|
||||
destructive: {
|
||||
DEFAULT: 'hsl(var(--destructive))',
|
||||
foreground: 'hsl(var(--destructive-foreground))',
|
||||
|
||||
120
packages/ui/lib/document-dropzone-constants.ts
Normal file
120
packages/ui/lib/document-dropzone-constants.ts
Normal file
@ -0,0 +1,120 @@
|
||||
import type { Variants } from 'framer-motion';
|
||||
|
||||
export const DocumentDropzoneContainerVariants: Variants = {
|
||||
initial: {
|
||||
scale: 1,
|
||||
},
|
||||
animate: {
|
||||
scale: 1,
|
||||
},
|
||||
hover: {
|
||||
transition: {
|
||||
staggerChildren: 0.05,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const DocumentDropzoneCardLeftVariants: Variants = {
|
||||
initial: {
|
||||
x: 40,
|
||||
y: -10,
|
||||
rotate: -14,
|
||||
},
|
||||
animate: {
|
||||
x: 40,
|
||||
y: -10,
|
||||
rotate: -14,
|
||||
},
|
||||
hover: {
|
||||
x: -25,
|
||||
y: -25,
|
||||
rotate: -22,
|
||||
},
|
||||
};
|
||||
|
||||
export const DocumentDropzoneCardRightVariants: Variants = {
|
||||
initial: {
|
||||
x: -40,
|
||||
y: -10,
|
||||
rotate: 14,
|
||||
},
|
||||
animate: {
|
||||
x: -40,
|
||||
y: -10,
|
||||
rotate: 14,
|
||||
},
|
||||
hover: {
|
||||
x: 25,
|
||||
y: -25,
|
||||
rotate: 22,
|
||||
},
|
||||
};
|
||||
|
||||
export const DocumentDropzoneCardCenterVariants: Variants = {
|
||||
initial: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
animate: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
hover: {
|
||||
x: 0,
|
||||
y: -25,
|
||||
},
|
||||
};
|
||||
|
||||
export const DocumentDropzoneDisabledCardLeftVariants: Variants = {
|
||||
initial: {
|
||||
x: 50,
|
||||
y: 0,
|
||||
rotate: -14,
|
||||
},
|
||||
animate: {
|
||||
x: 50,
|
||||
y: 0,
|
||||
rotate: -14,
|
||||
},
|
||||
hover: {
|
||||
x: 30,
|
||||
y: 0,
|
||||
rotate: -17,
|
||||
transition: { type: 'spring', duration: 0.3, stiffness: 500 },
|
||||
},
|
||||
};
|
||||
|
||||
export const DocumentDropzoneDisabledCardRightVariants: Variants = {
|
||||
initial: {
|
||||
x: -50,
|
||||
y: 0,
|
||||
rotate: 14,
|
||||
},
|
||||
animate: {
|
||||
x: -50,
|
||||
y: 0,
|
||||
rotate: 14,
|
||||
},
|
||||
hover: {
|
||||
x: -30,
|
||||
y: 0,
|
||||
rotate: 17,
|
||||
transition: { type: 'spring', duration: 0.3, stiffness: 500 },
|
||||
},
|
||||
};
|
||||
|
||||
export const DocumentDropzoneDisabledCardCenterVariants: Variants = {
|
||||
initial: {
|
||||
x: -10,
|
||||
y: 0,
|
||||
},
|
||||
animate: {
|
||||
x: -10,
|
||||
y: 0,
|
||||
},
|
||||
hover: {
|
||||
x: [-15, -10, -5, -10],
|
||||
y: 0,
|
||||
transition: { type: 'spring', duration: 0.3, stiffness: 1000 },
|
||||
},
|
||||
};
|
||||
@ -115,7 +115,12 @@ export function DataTable<TData, TValue>({
|
||||
table.getRowModel().rows.map((row) => (
|
||||
<TableRow key={row.id} data-state={row.getIsSelected() && 'selected'}>
|
||||
{row.getVisibleCells().map((cell) => (
|
||||
<TableCell key={cell.id}>
|
||||
<TableCell
|
||||
key={cell.id}
|
||||
style={{
|
||||
width: `${cell.column.getSize()}px`,
|
||||
}}
|
||||
>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</TableCell>
|
||||
))}
|
||||
|
||||
@ -1,90 +1,27 @@
|
||||
'use client';
|
||||
|
||||
import type { Variants } from 'framer-motion';
|
||||
import Link from 'next/link';
|
||||
|
||||
import { motion } from 'framer-motion';
|
||||
import { Plus } from 'lucide-react';
|
||||
import { AlertTriangle, Plus } from 'lucide-react';
|
||||
import { useDropzone } from 'react-dropzone';
|
||||
|
||||
import { APP_DOCUMENT_UPLOAD_SIZE_LIMIT } from '@documenso/lib/constants/app';
|
||||
import { APP_DOCUMENT_UPLOAD_SIZE_LIMIT, IS_BILLING_ENABLED } from '@documenso/lib/constants/app';
|
||||
import { megabytesToBytes } from '@documenso/lib/universal/unit-convertions';
|
||||
|
||||
import {
|
||||
DocumentDropzoneCardCenterVariants,
|
||||
DocumentDropzoneCardLeftVariants,
|
||||
DocumentDropzoneCardRightVariants,
|
||||
DocumentDropzoneContainerVariants,
|
||||
DocumentDropzoneDisabledCardCenterVariants,
|
||||
DocumentDropzoneDisabledCardLeftVariants,
|
||||
DocumentDropzoneDisabledCardRightVariants,
|
||||
} from '../lib/document-dropzone-constants';
|
||||
import { cn } from '../lib/utils';
|
||||
import { Button } from './button';
|
||||
import { Card, CardContent } from './card';
|
||||
|
||||
const DocumentDropzoneContainerVariants: Variants = {
|
||||
initial: {
|
||||
scale: 1,
|
||||
},
|
||||
animate: {
|
||||
scale: 1,
|
||||
},
|
||||
hover: {
|
||||
transition: {
|
||||
staggerChildren: 0.05,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const DocumentDropzoneCardLeftVariants: Variants = {
|
||||
initial: {
|
||||
x: 40,
|
||||
y: -10,
|
||||
rotate: -14,
|
||||
},
|
||||
animate: {
|
||||
x: 40,
|
||||
y: -10,
|
||||
rotate: -14,
|
||||
},
|
||||
hover: {
|
||||
x: -25,
|
||||
y: -25,
|
||||
rotate: -22,
|
||||
},
|
||||
};
|
||||
|
||||
const DocumentDropzoneCardRightVariants: Variants = {
|
||||
initial: {
|
||||
x: -40,
|
||||
y: -10,
|
||||
rotate: 14,
|
||||
},
|
||||
animate: {
|
||||
x: -40,
|
||||
y: -10,
|
||||
rotate: 14,
|
||||
},
|
||||
hover: {
|
||||
x: 25,
|
||||
y: -25,
|
||||
rotate: 22,
|
||||
},
|
||||
};
|
||||
|
||||
const DocumentDropzoneCardCenterVariants: Variants = {
|
||||
initial: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
animate: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
hover: {
|
||||
x: 0,
|
||||
y: -25,
|
||||
},
|
||||
};
|
||||
|
||||
const DocumentDescription = {
|
||||
document: {
|
||||
headline: 'Add a document',
|
||||
},
|
||||
template: {
|
||||
headline: 'Upload Template Document',
|
||||
},
|
||||
};
|
||||
|
||||
export type DocumentDropzoneProps = {
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
@ -123,68 +60,108 @@ export const DocumentDropzone = ({
|
||||
maxSize: megabytesToBytes(APP_DOCUMENT_UPLOAD_SIZE_LIMIT),
|
||||
});
|
||||
|
||||
const heading = {
|
||||
document: disabled ? 'You have reached your document limit.' : 'Add a document',
|
||||
template: 'Upload Template Document',
|
||||
};
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
className={cn('flex aria-disabled:cursor-not-allowed', className)}
|
||||
variants={DocumentDropzoneContainerVariants}
|
||||
initial="initial"
|
||||
animate="animate"
|
||||
whileHover="hover"
|
||||
aria-disabled={disabled}
|
||||
>
|
||||
<Card
|
||||
role="button"
|
||||
className={cn(
|
||||
'focus-visible:ring-ring ring-offset-background flex flex-1 cursor-pointer flex-col items-center justify-center focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 aria-disabled:pointer-events-none aria-disabled:opacity-60',
|
||||
'focus-visible:ring-ring ring-offset-background group flex flex-1 cursor-pointer flex-col items-center justify-center focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2',
|
||||
className,
|
||||
)}
|
||||
gradient={true}
|
||||
gradient={!disabled}
|
||||
degrees={120}
|
||||
aria-disabled={disabled}
|
||||
{...getRootProps()}
|
||||
{...props}
|
||||
>
|
||||
<CardContent className="text-muted-foreground/40 flex flex-col items-center justify-center p-6">
|
||||
{/* <FilePlus strokeWidth="1px" className="h-16 w-16"/> */}
|
||||
<div className="flex">
|
||||
<motion.div
|
||||
className="border-muted-foreground/20 group-hover:border-documenso/80 dark:bg-muted/80 a z-10 flex aspect-[3/4] w-24 origin-top-right -rotate-[22deg] flex-col gap-y-1 rounded-lg border bg-white/80 px-2 py-4 backdrop-blur-sm"
|
||||
variants={!disabled ? DocumentDropzoneCardLeftVariants : undefined}
|
||||
>
|
||||
<div className="bg-muted-foreground/20 group-hover:bg-documenso h-2 w-full rounded-[2px]" />
|
||||
<div className="bg-muted-foreground/20 group-hover:bg-documenso h-2 w-5/6 rounded-[2px]" />
|
||||
<div className="bg-muted-foreground/20 group-hover:bg-documenso h-2 w-full rounded-[2px]" />
|
||||
</motion.div>
|
||||
{disabled ? (
|
||||
// Disabled State
|
||||
<div className="flex">
|
||||
<motion.div
|
||||
className="group-hover:bg-destructive/2 border-muted-foreground/20 group-hover:border-destructive/10 dark:bg-muted/80 a z-10 flex aspect-[3/4] w-24 origin-top-right -rotate-[22deg] flex-col gap-y-1 rounded-lg border bg-white/80 px-2 py-4 backdrop-blur-sm"
|
||||
variants={DocumentDropzoneDisabledCardLeftVariants}
|
||||
>
|
||||
<div className="bg-muted-foreground/10 group-hover:bg-destructive/10 h-2 w-full rounded-[2px]" />
|
||||
<div className="bg-muted-foreground/10 group-hover:bg-destructive/10 h-2 w-5/6 rounded-[2px]" />
|
||||
<div className="bg-muted-foreground/10 group-hover:bg-destructive/10 h-2 w-full rounded-[2px]" />
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
className="border-muted-foreground/20 group-hover:border-documenso/80 dark:bg-muted/80 z-20 flex aspect-[3/4] w-24 flex-col items-center justify-center gap-y-1 rounded-lg border bg-white/80 px-2 py-4 backdrop-blur-sm"
|
||||
variants={!disabled ? DocumentDropzoneCardCenterVariants : undefined}
|
||||
>
|
||||
<Plus
|
||||
strokeWidth="2px"
|
||||
className="text-muted-foreground/20 group-hover:text-documenso h-12 w-12"
|
||||
/>
|
||||
</motion.div>
|
||||
<motion.div
|
||||
className="group-hover:bg-destructive/5 border-muted-foreground/20 group-hover:border-destructive/50 dark:bg-muted/80 z-20 flex aspect-[3/4] w-24 flex-col items-center justify-center gap-y-1 rounded-lg border bg-white/80 px-2 py-4 backdrop-blur-sm"
|
||||
variants={DocumentDropzoneDisabledCardCenterVariants}
|
||||
>
|
||||
<AlertTriangle
|
||||
strokeWidth="2px"
|
||||
className="text-muted-foreground/20 group-hover:text-destructive h-12 w-12"
|
||||
/>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
className="border-muted-foreground/20 group-hover:border-documenso/80 dark:bg-muted/80 z-10 flex aspect-[3/4] w-24 origin-top-left rotate-[22deg] flex-col gap-y-1 rounded-lg border bg-white/80 px-2 py-4 backdrop-blur-sm"
|
||||
variants={!disabled ? DocumentDropzoneCardRightVariants : undefined}
|
||||
>
|
||||
<div className="bg-muted-foreground/20 group-hover:bg-documenso h-2 w-full rounded-[2px]" />
|
||||
<div className="bg-muted-foreground/20 group-hover:bg-documenso h-2 w-5/6 rounded-[2px]" />
|
||||
<div className="bg-muted-foreground/20 group-hover:bg-documenso h-2 w-full rounded-[2px]" />
|
||||
</motion.div>
|
||||
</div>
|
||||
<motion.div
|
||||
className="group-hover:bg-destructive/2 border-muted-foreground/20 group-hover:border-destructive/10 dark:bg-muted/80 z-10 flex aspect-[3/4] w-24 origin-top-left rotate-[22deg] flex-col gap-y-1 rounded-lg border bg-white/80 px-2 py-4 backdrop-blur-sm"
|
||||
variants={DocumentDropzoneDisabledCardRightVariants}
|
||||
>
|
||||
<div className="bg-muted-foreground/10 group-hover:bg-destructive/10 h-2 w-full rounded-[2px]" />
|
||||
<div className="bg-muted-foreground/10 group-hover:bg-destructive/10 h-2 w-5/6 rounded-[2px]" />
|
||||
<div className="bg-muted-foreground/10 group-hover:bg-destructive/10 h-2 w-full rounded-[2px]" />
|
||||
</motion.div>
|
||||
</div>
|
||||
) : (
|
||||
// Non Disabled State
|
||||
<div className="flex">
|
||||
<motion.div
|
||||
className="border-muted-foreground/20 group-hover:border-documenso/80 dark:bg-muted/80 a z-10 flex aspect-[3/4] w-24 origin-top-right -rotate-[22deg] flex-col gap-y-1 rounded-lg border bg-white/80 px-2 py-4 backdrop-blur-sm"
|
||||
variants={DocumentDropzoneCardLeftVariants}
|
||||
>
|
||||
<div className="bg-muted-foreground/20 group-hover:bg-documenso h-2 w-full rounded-[2px]" />
|
||||
<div className="bg-muted-foreground/20 group-hover:bg-documenso h-2 w-5/6 rounded-[2px]" />
|
||||
<div className="bg-muted-foreground/20 group-hover:bg-documenso h-2 w-full rounded-[2px]" />
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
className="border-muted-foreground/20 group-hover:border-documenso/80 dark:bg-muted/80 z-20 flex aspect-[3/4] w-24 flex-col items-center justify-center gap-y-1 rounded-lg border bg-white/80 px-2 py-4 backdrop-blur-sm"
|
||||
variants={DocumentDropzoneCardCenterVariants}
|
||||
>
|
||||
<Plus
|
||||
strokeWidth="2px"
|
||||
className="text-muted-foreground/20 group-hover:text-documenso h-12 w-12"
|
||||
/>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
className="border-muted-foreground/20 group-hover:border-documenso/80 dark:bg-muted/80 z-10 flex aspect-[3/4] w-24 origin-top-left rotate-[22deg] flex-col gap-y-1 rounded-lg border bg-white/80 px-2 py-4 backdrop-blur-sm"
|
||||
variants={DocumentDropzoneCardRightVariants}
|
||||
>
|
||||
<div className="bg-muted-foreground/20 group-hover:bg-documenso h-2 w-full rounded-[2px]" />
|
||||
<div className="bg-muted-foreground/20 group-hover:bg-documenso h-2 w-5/6 rounded-[2px]" />
|
||||
<div className="bg-muted-foreground/20 group-hover:bg-documenso h-2 w-full rounded-[2px]" />
|
||||
</motion.div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<input {...getInputProps()} />
|
||||
|
||||
<p className="group-hover:text-foreground text-muted-foreground mt-8 font-medium">
|
||||
{DocumentDescription[type].headline}
|
||||
</p>
|
||||
<p className="text-foreground mt-8 font-medium">{heading[type]}</p>
|
||||
|
||||
<p className="text-muted-foreground/80 mt-1 text-sm">
|
||||
<p className="text-muted-foreground/80 mt-1 text-center text-sm">
|
||||
{disabled ? disabledMessage : 'Drag & drop your PDF here.'}
|
||||
</p>
|
||||
|
||||
{disabled && IS_BILLING_ENABLED() && (
|
||||
<Button className="hover:bg-warning/80 bg-warning mt-4 w-32" asChild>
|
||||
<Link href="/settings/billing">Upgrade</Link>
|
||||
</Button>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</motion.div>
|
||||
|
||||
@ -79,7 +79,7 @@ const ToastClose = React.forwardRef<
|
||||
<ToastPrimitives.Close
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'text-foreground/50 hover:text-foreground absolute right-2 top-2 rounded-md p-1 opacity-0 transition-opacity focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600',
|
||||
'text-foreground/50 hover:text-foreground absolute right-2 top-2 rounded-md p-1 opacity-100 transition-opacity focus:opacity-100 focus:outline-none focus:ring-2 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600 md:opacity-0 group-hover:md:opacity-100',
|
||||
className,
|
||||
)}
|
||||
toast-close=""
|
||||
|
||||
@ -42,6 +42,8 @@
|
||||
--ring: 95.08 71.08% 67.45%;
|
||||
|
||||
--radius: 0.5rem;
|
||||
|
||||
--warning: 54 96% 45%;
|
||||
}
|
||||
|
||||
.dark {
|
||||
@ -79,6 +81,8 @@
|
||||
--ring: 95.08 71.08% 67.45%;
|
||||
|
||||
--radius: 0.5rem;
|
||||
|
||||
--warning: 54 96% 45%;
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,6 +91,11 @@
|
||||
@apply border-border;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
scrollbar-gutter: stable;
|
||||
}
|
||||
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
font-feature-settings: 'rlig' 1, 'calt' 1;
|
||||
|
||||
Reference in New Issue
Block a user