PluginProbe
Code Snippets / 3.10.0-beta.1
Code Snippets v3.10.0-beta.1
4.0.0-beta.2 3.10.2 3.10.1 3.10.0 3.10.0-beta.2 3.10.0-beta.1 4.0.0-beta.1 3.9.6 trunk 2.10.0 2.10.1 2.12.0 2.12.1 2.13.0 2.13.1 2.13.2 2.13.3 2.14.0 2.14.1 2.14.2 2.14.3 2.14.4 2.14.5 2.14.6 3.0.0 All 65 releases
code-snippets / js / components / common / DeleteButton.tsx

DeleteButton.tsx in Code Snippets 3.10.0-beta.1, at js/components/common/DeleteButton.tsx

127 lines 3.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import React, { useState } from 'react'
2 import { __ } from '@wordpress/i18n'
3 import { createInterpolateElement } from '@wordpress/element'
4 import { useSnippetsAPI } from '../../hooks/useSnippetsAPI'
5 import { Button } from './Button'
6 import { ConfirmDialog } from './ConfirmDialog'
7 import type { ReactNode } from 'react'
8 import type { Snippet } from '../../types/Snippet'
9 import type { ButtonProps } from './Button'
10
11 const TrashActiveConfirmMessage = () =>
12 <>
13 <p style={{ marginBlockStart: 0 }}>
14 {createInterpolateElement(
15 __('This snippet is currently <strong>active</strong>.', 'code-snippets'),
16 { strong: <strong /> }
17 )}
18 </p>
19
20 <p>{__('Moving it to the trash will also deactivate it.', 'code-snippets')}</p>
21 </>
22
23 const PermanentDeleteConfirmMessage = () =>
24 <>
25 <p style={{ marginBlockStart: 0 }}>
26 {createInterpolateElement(
27 __('The snippet will be <strong>permanently deleted</strong>.', 'code-snippets'),
28 { strong: <strong /> }
29 )}
30 </p>
31
32 <p>{__('This action cannot be undone.', 'code-snippets')}</p>
33 </>
34
35 export interface UseDeleteSnippetOptions {
36 snippet: Snippet
37 setIsWorking?: (isWorking: boolean) => void
38 onSuccess?: () => Promise<void> | void
39 onError?: (error: unknown) => void
40 }
41
42 export interface UseDeleteSnippetResult {
43 requestDelete: () => void
44 confirmDialog: ReactNode
45 }
46
47 /**
48 * Deletion flow shared by every control that removes a snippet: active and
49 * trashed snippets prompt for confirmation before the API call, while
50 * inactive snippets are trashed immediately. Callers must render the returned
51 * dialog somewhere that stays mounted while the confirmation is open.
52 */
53 export const useDeleteSnippet = ({
54 snippet,
55 setIsWorking,
56 onSuccess,
57 onError
58 }: UseDeleteSnippetOptions): UseDeleteSnippetResult => {
59 const snippetsAPI = useSnippetsAPI()
60 const [isDialogOpen, setIsDialogOpen] = useState(false)
61
62 const handleDelete = () => {
63 setIsWorking?.(true)
64
65 snippetsAPI.delete(snippet)
66 .then(() => onSuccess?.())
67 .catch((error: unknown) => onError?.(error))
68 .finally(() => setIsWorking?.(false))
69 }
70
71 const requestDelete = () => {
72 if (snippet.active || snippet.trashed) {
73 setIsDialogOpen(true)
74 } else {
75 handleDelete()
76 }
77 }
78
79 const confirmDialog =
80 <ConfirmDialog
81 open={isDialogOpen}
82 title={__('Are you sure?', 'code-snippets')}
83 confirmLabel={snippet.trashed ? __('Delete', 'code-snippets') : __('Trash', 'code-snippets')}
84 confirmButtonClassName="is-destructive"
85 onCancel={() => setIsDialogOpen(false)}
86 onConfirm={() => {
87 setIsDialogOpen(false)
88 handleDelete()
89 }}
90 >
91 {snippet.trashed ? <PermanentDeleteConfirmMessage /> : <TrashActiveConfirmMessage />}
92 </ConfirmDialog>
93
94 return { requestDelete, confirmDialog }
95 }
96
97 export interface DeleteButtonProps
98 extends Omit<ButtonProps, 'onError'>, Omit<UseDeleteSnippetOptions, 'snippet'> {
99 snippet: Snippet
100 }
101
102 export const DeleteButton: React.FC<DeleteButtonProps> = ({
103 snippet,
104 onSuccess,
105 onError,
106 className = 'delete-button',
107 setIsWorking,
108 ...buttonProps
109 }) => {
110 const { requestDelete, confirmDialog } = useDeleteSnippet({
111 snippet,
112 setIsWorking,
113 onSuccess,
114 onError
115 })
116
117 return (
118 <>
119 <Button className={className} {...buttonProps} onClick={requestDelete}>
120 {snippet.trashed ? __('Delete Permanently', 'code-snippets') : __('Trash', 'code-snippets')}
121 </Button>
122
123 {confirmDialog}
124 </>
125 )
126 }
127