PluginProbe
Code Snippets / trunk
Code Snippets vtrunk
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
← All changes | js/components/ManageMenu/SnippetsTable/RowActions.tsx +54 -58 3.10.0-beta.1 → trunk View file →
@@ -5,12 +5,12 @@
5 5 import { useSnippetsAPI } from '../../../hooks/useSnippetsAPI'
6 6 import { useSnippetsList } from '../../../hooks/useSnippetsList'
7 7 import { downloadSnippetExportFile } from '../../../utils/files'
8 8 import { isNetworkAdmin } from '../../../utils/screen'
9 -import { cloneSnippetObject, getSnippetDisplayName, getSnippetEditUrl, getSnippetType } from '../../../utils/snippets/snippets'
9 +import { cloneSnippetObject, getSnippetEditUrl } from '../../../utils/snippets/snippets'
10 10 import { Button } from '../../common/Button'
11 -import { DeleteButton } from '../../common/DeleteButton'
12 -import { SnippetPreviewModal } from '../../common/SnippetPreviewModal'
11 +import { SnippetPreviewModal } from '../../common/snippets/SnippetPreviewModal'
12 +import { ConfirmDeleteDialog, useDeleteSnippet } from '../../common/snippets/ConfirmDeleteDialog'
13 13 import type { ReactNode } from 'react'
14 14 import type { Snippet } from '../../../types/Snippet'
15 15
16 16 interface RowActionsProps {
@@ -16,9 +16,9 @@
16 16 interface RowActionsProps {
17 17 snippet: Snippet
18 18 }
19 19
20 -const PreviewLink: React.FC<RowActionsProps> = ({ snippet }) => {
20 +const PreviewButton: React.FC<RowActionsProps> = ({ snippet }) => {
21 21 const [isPreviewOpen, setIsPreviewOpen] = useState(false)
22 22
23 23 return (
24 24 <>
@@ -25,16 +25,13 @@
25 25 <Button link onClick={() => setIsPreviewOpen(true)}>
26 26 {__('Preview', 'code-snippets')}
27 27 </Button>
28 28
29 - <SnippetPreviewModal
30 - title={getSnippetDisplayName(snippet)}
31 - code={snippet.code}
32 - type={getSnippetType(snippet)}
33 - isOpen={isPreviewOpen}
34 - setIsOpen={setIsPreviewOpen}
35 - snippet={snippet}
36 - />
29 + {isPreviewOpen && (
30 + <SnippetPreviewModal
31 + snippet={snippet}
32 + setIsOpen={setIsPreviewOpen}
33 + />)}
37 34 </>
38 35 )
39 36 }
40 37
@@ -50,30 +47,8 @@
50 47
51 48 const SnippetActionButton: React.FC<SnippetActionButtonProps> = ({ action, label, workingLabel, failedLabel, className }) => {
52 49 const [status, setStatus] = useState(SnippetActionStatus.Ready)
53 50
54 - const ButtonContent = () => {
55 - switch (status) {
56 - case SnippetActionStatus.Working:
57 - return (
58 - <span className="snippet-row-action-feedback">
59 - <Spinner /> {workingLabel ?? __('Loading…', 'code-snippets')}
60 - </span>
61 - )
62 -
63 - case SnippetActionStatus.Errored:
64 - return (
65 - <span className="snippet-row-action-error">
66 - <span className="dashicons dashicons-warning"></span>
67 - {failedLabel ?? __('Failed', 'code-snippets')}
68 - </span>
69 - )
70 -
71 - default:
72 - return label
73 - }
74 - }
75 -
76 51 return (
77 52 <Button
78 53 link
79 54 className={classnames(className, { 'is-busy': status === SnippetActionStatus.Working })}
@@ -100,43 +75,64 @@
100 75 }
101 76 }
102 77 }}
103 78 >
104 - <ButtonContent />
79 + {(() => {
80 + switch (status) {
81 + case SnippetActionStatus.Working:
82 + return (
83 + <span className="snippet-row-action-feedback">
84 + <Spinner /> {workingLabel ?? __('Loading…', 'code-snippets')}
85 + </span>
86 + )
87 +
88 + case SnippetActionStatus.Errored:
89 + return (
90 + <span className="snippet-row-action-error">
91 + <span className="dashicons dashicons-warning"></span>
92 + {failedLabel ?? __('Failed', 'code-snippets')}
93 + </span>
94 + )
95 +
96 + default:
97 + return label
98 + }
99 + })()}
105 100 </Button>
106 101 )
107 102 }
103 +const DeleteActionLink: React.FC<RowActionsProps> = ({ snippet }) => {
104 + const { refreshSnippetsList } = useSnippetsList()
105 + const { requestDelete, deleteDialogProps } = useDeleteSnippet({ snippet, onSuccess: refreshSnippetsList })
108 106
109 -const DeleteActionLink: React.FC<{ snippet: Snippet; onSuccess: () => Promise<void> }> = ({ snippet, onSuccess }) => {
110 - const [isDeleting, setIsDeleting] = useState(false)
111 -
112 107 return (
113 108 <>
114 - <DeleteButton
115 - link
116 - className={classnames('delete')}
117 - snippet={snippet}
118 - setIsWorking={setIsDeleting}
119 - onSuccess={onSuccess}
109 + <SnippetActionButton
110 + action={requestDelete}
111 + className="delete"
112 + label={snippet.trashed ? __('Delete Permanently', 'code-snippets') : __('Trash', 'code-snippets')}
113 + workingLabel={snippet.trashed ? __('Deleting…', 'code-snippets') : __('Trashing…', 'code-snippets')}
114 + failedLabel={__('Failed to delete', 'code-snippets')}
120 115 />
121 - {isDeleting ? <span className="snippet-row-action-feedback"><Spinner /> {__('Deleting…', 'code-snippets')}</span> : null}
116 +
117 + <ConfirmDeleteDialog {...deleteDialogProps} />
122 118 </>
123 119 )
124 120 }
125 121
126 -const ActionLinks = ({ snippet }: { snippet: Snippet }) => {
122 +const ActionLinks: React.FC<RowActionsProps> = ({ snippet }) => {
127 123 const api = useSnippetsAPI()
128 124 const { refreshSnippetsList } = useSnippetsList()
129 125
130 - const Preview = !snippet.trashed ? <PreviewLink snippet={snippet} /> : null
126 + const previewButton = !snippet.trashed ? <PreviewButton snippet={snippet} /> : null
131 127
132 - const Edit = !snippet.trashed
128 + const editLink = !snippet.trashed
133 129 ? <a href={getSnippetEditUrl(snippet)}>
134 130 {snippet.locked ? __('View', 'code-snippets') : __('Edit', 'code-snippets')}
135 131 </a>
136 132 : null
137 133
138 - const Clone = !snippet.trashed
134 + const cloneButton = !snippet.trashed
139 135 ? <SnippetActionButton
140 136 label={__('Clone', 'code-snippets')}
141 137 workingLabel={__('Cloning…', 'code-snippets')}
142 138 action={() => api.create(cloneSnippetObject(snippet)).then(refreshSnippetsList)}
@@ -142,9 +138,9 @@
142 138 action={() => api.create(cloneSnippetObject(snippet)).then(refreshSnippetsList)}
143 139 />
144 140 : null
145 141
146 - const Export = !snippet.trashed
142 + const exportButton = !snippet.trashed
147 143 ? <SnippetActionButton
148 144 label={__('Export', 'code-snippets')}
149 145 workingLabel={__('Exporting…', 'code-snippets')}
150 146 action={() =>
@@ -152,9 +148,9 @@
152 148 .then(response => downloadSnippetExportFile(response, snippet))}
153 149 />
154 150 : null
155 151
156 - const Restore = snippet.trashed
152 + const restoreButton = snippet.trashed
157 153 ? <SnippetActionButton
158 154 label={__('Restore', 'code-snippets')}
159 155 workingLabel={__('Restoring…', 'code-snippets')}
160 156 action={() => api.restore(snippet).then(refreshSnippetsList)}
@@ -160,19 +156,19 @@
160 156 action={() => api.restore(snippet).then(refreshSnippetsList)}
161 157 />
162 158 : null
163 159
164 - const Delete = !snippet.locked || snippet.trashed
165 - ? <DeleteActionLink snippet={snippet} onSuccess={refreshSnippetsList} />
160 + const deleteButton = !snippet.locked || snippet.trashed
161 + ? <DeleteActionLink snippet={snippet} />
166 162 : null
167 163
168 164 return (
169 165 <>
170 - {[Preview, Edit, Clone, Restore, Export, Delete]
171 - .filter(Action => Action)
166 + {[previewButton, editLink, cloneButton, restoreButton, exportButton, deleteButton]
167 + .filter(action => action)
172 168 .reduce<ReactNode>(
173 - (Actions, Action) =>
174 - null === Actions ? <>{Action}</> : <>{Actions} | {Action}</>,
169 + (actions, action) =>
170 + null === actions ? <>{action}</> : <>{actions} | {action}</>,
175 171 null)}
176 172 </>
177 173 )
178 174 }
@@ -188,9 +184,9 @@
188 184 )
189 185 }
190 186
191 187 if (snippet.shared_network && !window.CODE_SNIPPETS_MANAGE?.hasNetworkCap) {
192 - return undefined
188 + return null
193 189 }
194 190
195 191 return (
196 192 <div className={classnames('row-actions', { visible: !snippet.trashed })}>