2023-10-06 22:54:24 +00:00
|
|
|
'use client';
|
|
|
|
|
|
|
|
|
|
import { useState } from 'react';
|
|
|
|
|
|
|
|
|
|
import Link from 'next/link';
|
|
|
|
|
|
2024-07-05 03:20:27 +00:00
|
|
|
import { Copy, Edit, MoreHorizontal, MoveRight, Share2Icon, Trash2 } from 'lucide-react';
|
2023-10-06 22:54:24 +00:00
|
|
|
import { useSession } from 'next-auth/react';
|
|
|
|
|
|
2024-06-02 15:49:09 +10:00
|
|
|
import { type FindTemplateRow } from '@documenso/lib/server-only/template/find-templates';
|
2023-10-06 22:54:24 +00:00
|
|
|
import {
|
|
|
|
|
DropdownMenu,
|
|
|
|
|
DropdownMenuContent,
|
|
|
|
|
DropdownMenuItem,
|
|
|
|
|
DropdownMenuLabel,
|
|
|
|
|
DropdownMenuTrigger,
|
|
|
|
|
} from '@documenso/ui/primitives/dropdown-menu';
|
|
|
|
|
|
|
|
|
|
import { DeleteTemplateDialog } from './delete-template-dialog';
|
|
|
|
|
import { DuplicateTemplateDialog } from './duplicate-template-dialog';
|
2024-07-05 03:20:27 +00:00
|
|
|
import { MoveTemplateDialog } from './move-template-dialog';
|
2024-06-02 15:49:09 +10:00
|
|
|
import { TemplateDirectLinkDialog } from './template-direct-link-dialog';
|
2023-10-06 22:54:24 +00:00
|
|
|
|
|
|
|
|
export type DataTableActionDropdownProps = {
|
2024-06-02 15:49:09 +10:00
|
|
|
row: FindTemplateRow;
|
2024-02-08 12:33:20 +11:00
|
|
|
templateRootPath: string;
|
|
|
|
|
teamId?: number;
|
2023-10-06 22:54:24 +00:00
|
|
|
};
|
|
|
|
|
|
2024-02-08 12:33:20 +11:00
|
|
|
export const DataTableActionDropdown = ({
|
|
|
|
|
row,
|
|
|
|
|
templateRootPath,
|
|
|
|
|
teamId,
|
|
|
|
|
}: DataTableActionDropdownProps) => {
|
2023-10-06 22:54:24 +00:00
|
|
|
const { data: session } = useSession();
|
|
|
|
|
|
|
|
|
|
const [isDeleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
2024-06-02 15:49:09 +10:00
|
|
|
const [isTemplateDirectLinkDialogOpen, setTemplateDirectLinkDialogOpen] = useState(false);
|
2023-10-06 22:54:24 +00:00
|
|
|
const [isDuplicateDialogOpen, setDuplicateDialogOpen] = useState(false);
|
2024-07-05 03:20:27 +00:00
|
|
|
const [isMoveDialogOpen, setMoveDialogOpen] = useState(false);
|
2023-10-06 22:54:24 +00:00
|
|
|
|
|
|
|
|
if (!session) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const isOwner = row.userId === session.user.id;
|
2024-02-08 12:33:20 +11:00
|
|
|
const isTeamTemplate = row.teamId === teamId;
|
2023-10-06 22:54:24 +00:00
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<DropdownMenu>
|
|
|
|
|
<DropdownMenuTrigger>
|
|
|
|
|
<MoreHorizontal className="text-muted-foreground h-5 w-5" />
|
|
|
|
|
</DropdownMenuTrigger>
|
|
|
|
|
|
|
|
|
|
<DropdownMenuContent className="w-52" align="start" forceMount>
|
|
|
|
|
<DropdownMenuLabel>Action</DropdownMenuLabel>
|
|
|
|
|
|
2024-02-08 12:33:20 +11:00
|
|
|
<DropdownMenuItem disabled={!isOwner && !isTeamTemplate} asChild>
|
|
|
|
|
<Link href={`${templateRootPath}/${row.id}`}>
|
2023-10-06 22:54:24 +00:00
|
|
|
<Edit className="mr-2 h-4 w-4" />
|
|
|
|
|
Edit
|
|
|
|
|
</Link>
|
|
|
|
|
</DropdownMenuItem>
|
|
|
|
|
|
2024-02-08 12:33:20 +11:00
|
|
|
<DropdownMenuItem
|
|
|
|
|
disabled={!isOwner && !isTeamTemplate}
|
|
|
|
|
onClick={() => setDuplicateDialogOpen(true)}
|
|
|
|
|
>
|
2023-10-06 22:54:24 +00:00
|
|
|
<Copy className="mr-2 h-4 w-4" />
|
|
|
|
|
Duplicate
|
|
|
|
|
</DropdownMenuItem>
|
|
|
|
|
|
2024-06-02 15:49:09 +10:00
|
|
|
<DropdownMenuItem onClick={() => setTemplateDirectLinkDialogOpen(true)}>
|
|
|
|
|
<Share2Icon className="mr-2 h-4 w-4" />
|
|
|
|
|
Direct link
|
|
|
|
|
</DropdownMenuItem>
|
|
|
|
|
|
2024-07-05 03:20:27 +00:00
|
|
|
{!teamId && (
|
|
|
|
|
<DropdownMenuItem onClick={() => setMoveDialogOpen(true)}>
|
|
|
|
|
<MoveRight className="mr-2 h-4 w-4" />
|
|
|
|
|
Move to Team
|
|
|
|
|
</DropdownMenuItem>
|
|
|
|
|
)}
|
|
|
|
|
|
2024-02-08 12:33:20 +11:00
|
|
|
<DropdownMenuItem
|
|
|
|
|
disabled={!isOwner && !isTeamTemplate}
|
|
|
|
|
onClick={() => setDeleteDialogOpen(true)}
|
|
|
|
|
>
|
2023-10-06 22:54:24 +00:00
|
|
|
<Trash2 className="mr-2 h-4 w-4" />
|
|
|
|
|
Delete
|
|
|
|
|
</DropdownMenuItem>
|
|
|
|
|
</DropdownMenuContent>
|
|
|
|
|
|
|
|
|
|
<DuplicateTemplateDialog
|
|
|
|
|
id={row.id}
|
2024-02-08 12:33:20 +11:00
|
|
|
teamId={teamId}
|
2023-10-06 22:54:24 +00:00
|
|
|
open={isDuplicateDialogOpen}
|
|
|
|
|
onOpenChange={setDuplicateDialogOpen}
|
|
|
|
|
/>
|
|
|
|
|
|
2024-06-02 15:49:09 +10:00
|
|
|
<TemplateDirectLinkDialog
|
|
|
|
|
template={row}
|
|
|
|
|
open={isTemplateDirectLinkDialogOpen}
|
|
|
|
|
onOpenChange={setTemplateDirectLinkDialogOpen}
|
|
|
|
|
/>
|
|
|
|
|
|
2024-07-05 03:20:27 +00:00
|
|
|
<MoveTemplateDialog
|
|
|
|
|
templateId={row.id}
|
|
|
|
|
open={isMoveDialogOpen}
|
|
|
|
|
onOpenChange={setMoveDialogOpen}
|
|
|
|
|
/>
|
|
|
|
|
|
2023-10-06 22:54:24 +00:00
|
|
|
<DeleteTemplateDialog
|
|
|
|
|
id={row.id}
|
feat: add more template API endpoints (#1198)
## Description
Update the API endpoint to support more actions for templates
## Changes Made
Add the following endpoints for templates:
- Get template
- Get templates
- Delete template
Get template(s) returns associated recipients and fields.
UI:
- Updated template delete button to have the destructive delete variant
## Testing Performed
Tested endpoints via /api/v1/openapi
Tested deleting templates via UI manually
## Test data
<details>
<summary>Delete template response</summary>
```json
{
"id": 32,
"type": "PRIVATE",
"title": "documenso-supporter-pledge.pdf",
"userId": 3,
"teamId": null,
"templateDocumentDataId": "clxva9b4h0001rrh7v0wdw97h",
"createdAt": "2024-06-26T03:35:45.065Z",
"updatedAt": "2024-06-26T03:35:45.065Z"
}
```
</details>
<details>
<summary>Get template response</summary>
```json
{
"id": 28,
"type": "PRIVATE",
"title": "blank_long.pdf",
"userId": 3,
"teamId": null,
"templateDocumentDataId": "clxu4vyty0003rrr52ue5ee4d",
"createdAt": "2024-06-25T08:17:38.418Z",
"updatedAt": "2024-06-26T03:36:33.890Z",
"templateMeta": {
"id": "clxvaacte0004rrh7s2k910nw",
"subject": "",
"message": "",
"timezone": "Australia/Melbourne",
"dateFormat": "yyyy-MM-dd hh:mm a",
"templateId": 28,
"redirectUrl": ""
},
"directLink": {
"token": "tBJHVFR75sC8m6hPfBTZd",
"enabled": true
},
"templateDocumentData": {
"id": "clxu4vyty0003rrr52ue5ee4d",
"type": "BYTES_64",
"data": "<PDF DATA>"
},
"Field": [
{
"id": 327,
"recipientId": 357,
"type": "SIGNATURE",
"page": 1,
"positionX": "55.8431952662722",
"positionY": "21.39588100686499",
"width": "29.58579881656805",
"height": "6.864988558352403"
},
{
"id": 328,
"recipientId": 357,
"type": "EMAIL",
"page": 1,
"positionX": "28.03254437869823",
"positionY": "72.99771167048056",
"width": "29.58579881656805",
"height": "6.864988558352403"
}
],
"Recipient": [
{
"id": 357,
"email": "direct.link@documenso.com",
"name": "Direct link recipient",
"authOptions": {
"accessAuth": null,
"actionAuth": null
},
"role": "SIGNER"
},
{
"id": 359,
"email": "example@documenso.com",
"name": "Example User",
"authOptions": {
"accessAuth": null,
"actionAuth": null
},
"role": "SIGNER"
}
]
}
```
</details>
<details>
<summary>Get templates response</summary>
```json
{
"templates": [
{
"id": 33,
"type": "PRIVATE",
"title": "documenso-supporter-pledge.pdf",
"userId": 3,
"teamId": null,
"templateDocumentDataId": "clxva9oaj0003rrh7hwdyg60o",
"createdAt": "2024-06-26T03:36:02.130Z",
"updatedAt": "2024-06-26T03:36:02.130Z",
"directLink": null,
"Field": [],
"Recipient": []
},
{
"id": 28,
"type": "PRIVATE",
"title": "blank_long.pdf",
"userId": 3,
"teamId": null,
"templateDocumentDataId": "clxu4vyty0003rrr52ue5ee4d",
"createdAt": "2024-06-25T08:17:38.418Z",
"updatedAt": "2024-06-26T03:36:33.890Z",
"directLink": {
"token": "tBJHVFR75sC8m6hPfBTZd",
"enabled": true
},
"Field": [
{
"id": 327,
"recipientId": 357,
"type": "SIGNATURE",
"page": 1,
"positionX": "55.8431952662722",
"positionY": "21.39588100686499",
"width": "29.58579881656805",
"height": "6.864988558352403"
},
{
"id": 328,
"recipientId": 357,
"type": "EMAIL",
"page": 1,
"positionX": "28.03254437869823",
"positionY": "72.99771167048056",
"width": "29.58579881656805",
"height": "6.864988558352403"
}
],
"Recipient": [
{
"id": 357,
"email": "direct.link@documenso.com",
"name": "Direct link recipient",
"authOptions": {
"accessAuth": null,
"actionAuth": null
},
"role": "SIGNER"
},
{
"id": 359,
"email": "example@documenso.com",
"name": "Example User",
"authOptions": {
"accessAuth": null,
"actionAuth": null
},
"role": "SIGNER"
}
]
}
],
"totalPages": 2
}
```
</details>
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Added support for team-based template deletion in the dashboard.
- Enhanced API to manage templates, including fetching and deleting
templates by team ID.
- **Bug Fixes**
- Improved error handling for template operations, ensuring better
feedback when templates are not found.
- **Refactor**
- Updated various components and functions to include `teamId` for more
robust template management.
- **Documentation**
- Expanded schema definitions to detail new structures for template and
team interactions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2024-06-27 15:44:16 +10:00
|
|
|
teamId={row.teamId || undefined}
|
2023-10-06 22:54:24 +00:00
|
|
|
open={isDeleteDialogOpen}
|
|
|
|
|
onOpenChange={setDeleteDialogOpen}
|
|
|
|
|
/>
|
|
|
|
|
</DropdownMenu>
|
|
|
|
|
);
|
|
|
|
|
};
|