PluginProbe
Code Snippets / 4.0.0-beta.2
Code Snippets v4.0.0-beta.2
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/TableColumns.tsx +66 -4 3.10.0 → 4.0.0-beta.2 View file →
@@ -1,7 +1,7 @@
1 1 import { humanTimeDiff } from '@wordpress/date'
2 2 import { RawHTML } from '@wordpress/element'
3 -import { __ } from '@wordpress/i18n'
3 +import { __, sprintf } from '@wordpress/i18n'
4 4 import React, { Fragment } from 'react'
5 5 import { useSnippetsAPI } from '../../../hooks/useSnippetsAPI'
6 6 import { useSnippetsList } from '../../../hooks/useSnippetsList'
7 7 import { handleUnknownError } from '../../../utils/errors'
@@ -6,8 +6,9 @@
6 6 import { useSnippetsList } from '../../../hooks/useSnippetsList'
7 7 import { handleUnknownError } from '../../../utils/errors'
8 8 import { isNetworkAdmin } from '../../../utils/screen'
9 9 import { getSnippetDisplayName, getSnippetEditUrl, getSnippetType } from '../../../utils/snippets/snippets'
10 +import { getRunOnceNonce } from '../../../utils/restAPI'
10 11 import { buildUrl } from '../../../utils/urls'
11 12 import { Badge } from '../../common/Badge'
12 13 import { SnippetPriorityInput } from '../../common/snippets/SnippetPriorityInput'
13 14 import { Tooltip } from '../../common/Tooltip'
@@ -21,13 +22,32 @@
21 22 interface ColumnProps {
22 23 snippet: Snippet
23 24 }
24 25
26 +const runOnceUrl = (snippet: Snippet, nonce: string): string =>
27 + buildUrl(window.location.href, {
28 + action: 'run-once',
29 + snippet: snippet.id,
30 + network: snippet.network ? 'true' : 'false',
31 + _wpnonce: nonce
32 + })
33 +
34 +// The rendered link carries the nonce from page load. Before any navigation
35 +// starts, whether a click, a middle-click or "open in new tab", the href is
36 +// rebuilt from the nonce the Heartbeat has refreshed since, so a page left open
37 +// still works.
25 38 const RunOnceButton: React.FC<ColumnProps> = ({ snippet }) =>
26 39 <a
27 40 className="snippet-execution-button"
28 41 title={__('Run Once', 'code-snippets')}
29 - href={buildUrl(window.location.href, { action: 'run-once', snippet: snippet.id })}
42 + href={runOnceUrl(snippet, window.CODE_SNIPPETS_MANAGE?.runOnceNonce ?? '')}
43 + onMouseDown={event => {
44 + event.currentTarget.href = runOnceUrl(snippet, getRunOnceNonce())
45 + }}
46 + onClick={event => {
47 + event.preventDefault()
48 + window.location.assign(runOnceUrl(snippet, getRunOnceNonce()))
49 + }}
30 50 >
31 51 <span className="screen-reader-text">{__('Run Once', 'code-snippets')}</span>
32 52 <span aria-hidden="true">&nbsp;</span>
33 53 </a>
@@ -95,9 +115,9 @@
95 115 </Tooltip>)}
96 116 </div>
97 117
98 118 export const SnippetName: React.FC<ColumnProps> = ({ snippet }) =>
99 - <>
119 + <span className="snippet-name-group">
100 120 {!snippet.trashed && (isNetworkAdmin() || !snippet.network || window.CODE_SNIPPETS_MANAGE?.hasNetworkCap)
101 121 ? <a
102 122 href={getSnippetEditUrl(snippet)}
103 123 className="snippet-name"
@@ -109,9 +129,9 @@
109 129 {getSnippetDisplayName(snippet)}
110 130 </span>}
111 131
112 132 {snippet.shared_network && <span className="badge">{__('Shared on Network', 'code-snippets')}</span>}
113 - </>
133 + </span>
114 134
115 135 const NameColumn: React.FC<ColumnProps> = ({ snippet }) =>
116 136 <>
117 137 <SnippetExtraIcons snippet={snippet} />
@@ -153,8 +173,38 @@
153 173 </time>
154 174 </span>
155 175 : <>&#8212;</>
156 176
177 +export const PriorityColumn: React.FC<ColumnProps> = ({ snippet }) =>
178 + <SnippetPriorityInput snippet={snippet} />
179 +
180 +export const getAuthorDisplayName = (snippet: Snippet): string =>
181 + (snippet.updatedBy ?? snippet.createdBy)?.displayName ?? ''
182 +
183 +const AuthorColumn: React.FC<ColumnProps> = ({ snippet }) => {
184 + const creator = snippet.createdBy
185 + const updater = snippet.updatedBy
186 + const primary = updater ?? creator
187 +
188 + if (!primary) {
189 + return <span className="snippet-author is-unknown">&#8212;</span>
190 + }
191 +
192 + const tooltip = creator && updater && creator.id !== updater.id
193 + ? sprintf(__('Created by %1$s ยท Last edited by %2$s', 'code-snippets'), creator.displayName, updater.displayName)
194 + : creator
195 + ? sprintf(__('Created by %s', 'code-snippets'), creator.displayName)
196 + : sprintf(__('Last edited by %s', 'code-snippets'), primary.displayName)
197 +
198 + return (
199 + <span className="snippet-author" title={tooltip}>
200 + {primary.avatarUrl &&
201 + <img className="snippet-author__avatar" src={primary.avatarUrl} alt="" width={20} height={20} />}
202 + <span className="snippet-author__name">{primary.displayName}</span>
203 + </span>
204 + )
205 +}
206 +
157 207 const baseTableColumns: ListTableColumn<Snippet>[] = [
158 208 {
159 209 id: 'activate',
160 210 title: <span className="screen-reader-text">{__('Activate', 'code-snippets')}</span>,
@@ -160,8 +210,14 @@
160 210 title: <span className="screen-reader-text">{__('Activate', 'code-snippets')}</span>,
161 211 render: snippet => <ActivateColumn snippet={snippet} />
162 212 },
163 213 {
214 + id: 'id',
215 + title: __('ID', 'code-snippets'),
216 + sortedValue: snippet => snippet.id,
217 + render: snippet => snippet.id
218 + },
219 + {
164 220 id: 'name',
165 221 title: __('Name', 'code-snippets'),
166 222 isPrimary: true,
167 223 sortedValue: snippet => getSnippetDisplayName(snippet).toLowerCase(),
@@ -193,8 +249,14 @@
193 249 id: 'priority',
194 250 title: __('Priority', 'code-snippets'),
195 251 sortedValue: snippet => snippet.priority,
196 252 render: snippet => <SnippetPriorityInput snippet={snippet} />
253 + },
254 + {
255 + id: 'author',
256 + title: __('Author', 'code-snippets'),
257 + sortedValue: snippet => getAuthorDisplayName(snippet).toLowerCase(),
258 + render: snippet => <AuthorColumn snippet={snippet} />
197 259 }
198 260 ]
199 261
200 262 export const getTableColumns = (hiddenColumns: Set<Key>): ListTableColumn<Snippet>[] =>