PluginProbe
Code Snippets / 3.10.2
Code Snippets v3.10.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
code-snippets / js / components / ManageMenu / SnippetsTable / TableColumns.tsx

TableColumns.tsx in Code Snippets 3.10.2, at js/components/ManageMenu/SnippetsTable/TableColumns.tsx

207 lines 6.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { humanTimeDiff } from '@wordpress/date'
2 import { RawHTML } from '@wordpress/element'
3 import { __ } from '@wordpress/i18n'
4 import React, { Fragment } from 'react'
5 import { useSnippetsAPI } from '../../../hooks/useSnippetsAPI'
6 import { useSnippetsList } from '../../../hooks/useSnippetsList'
7 import { handleUnknownError } from '../../../utils/errors'
8 import { isNetworkAdmin } from '../../../utils/screen'
9 import { getSnippetDisplayName, getSnippetEditUrl, getSnippetType } from '../../../utils/snippets/snippets'
10 import { buildUrl } from '../../../utils/urls'
11 import { Badge } from '../../common/Badge'
12 import { SnippetPriorityInput } from '../../common/snippets/SnippetPriorityInput'
13 import { Tooltip } from '../../common/Tooltip'
14 import { RowActions } from './RowActions'
15 import { useFilteredSnippets } from './WithFilteredSnippetsContext'
16 import { useSnippetsFilters } from './WithSnippetsTableFilters'
17 import type { Key } from 'react'
18 import type { Snippet } from '../../../types/Snippet'
19 import type { ListTableColumn } from '../../common/ListTable'
20
21 interface ColumnProps {
22 snippet: Snippet
23 }
24
25 const RunOnceButton: React.FC<ColumnProps> = ({ snippet }) =>
26 <a
27 className="snippet-execution-button"
28 title={__('Run Once', 'code-snippets')}
29 href={buildUrl(window.location.href, {
30 action: 'run-once',
31 snippet: snippet.id,
32 network: snippet.network ? 'true' : 'false',
33 _wpnonce: window.CODE_SNIPPETS_MANAGE?.runOnceNonce ?? ''
34 })}
35 >
36 <span className="screen-reader-text">{__('Run Once', 'code-snippets')}</span>
37 <span aria-hidden="true">&nbsp;</span>
38 </a>
39
40 const ActivationSwitch: React.FC<ColumnProps> = ({ snippet }) => {
41 const { activate, deactivate } = useSnippetsAPI()
42 const { refreshSnippetsList } = useSnippetsList()
43
44 const actionText = snippet.network && !snippet.shared_network
45 ? snippet.active ? __('Network Deactivate', 'code-snippets') : __('Network Activate', 'code-snippets')
46 : snippet.active ? __('Deactivate', 'code-snippets') : __('Activate', 'code-snippets')
47
48 return (
49 <input
50 id={`snippet-${snippet.id}-switch`}
51 type="checkbox"
52 role="switch"
53 checked={snippet.active}
54 aria-checked={snippet.active}
55 className="switch"
56 title={actionText}
57 aria-label={actionText}
58 onChange={() => {
59 (snippet.active ? deactivate(snippet) : activate(snippet))
60 .then(refreshSnippetsList)
61 .catch(handleUnknownError)
62 }}
63 />
64 )
65 }
66
67 export const ActivateColumn: React.FC<ColumnProps> = ({ snippet }) => {
68 const { activeByCondition } = useFilteredSnippets()
69
70 if (snippet.trashed) {
71 return ''
72 }
73
74 switch (snippet.scope) {
75 case 'single-use':
76 return <RunOnceButton snippet={snippet} />
77
78 case 'condition':
79 return (
80 <a className="snippet-condition-count" href={getSnippetEditUrl(snippet)}>
81 {activeByCondition.get(snippet.id)?.length ?? 0}
82 </a>
83 )
84
85 default:
86 return <ActivationSwitch snippet={snippet} />
87 }
88 }
89
90 export const SnippetExtraIcons: React.FC<ColumnProps> = ({ snippet }) =>
91 <div className="extra-icons">
92 {snippet.locked && (
93 <Tooltip
94 inline
95 end
96 label={__('About snippet lock', 'code-snippets')}
97 icon={<span className="dashicons dashicons-lock" aria-hidden="true"></span>}
98 >
99 {__('This snippet is locked and cannot be modified.', 'code-snippets')}
100 </Tooltip>)}
101 </div>
102
103 export const SnippetName: React.FC<ColumnProps> = ({ snippet }) =>
104 <>
105 {!snippet.trashed && (isNetworkAdmin() || !snippet.network || window.CODE_SNIPPETS_MANAGE?.hasNetworkCap)
106 ? <a
107 href={getSnippetEditUrl(snippet)}
108 className="snippet-name"
109 title={getSnippetDisplayName(snippet)}
110 >
111 {getSnippetDisplayName(snippet)}
112 </a>
113 : <span className="snippet-name" title={getSnippetDisplayName(snippet)}>
114 {getSnippetDisplayName(snippet)}
115 </span>}
116
117 {snippet.shared_network && <span className="badge">{__('Shared on Network', 'code-snippets')}</span>}
118 </>
119
120 const NameColumn: React.FC<ColumnProps> = ({ snippet }) =>
121 <>
122 <SnippetExtraIcons snippet={snippet} />
123 <SnippetName snippet={snippet} />
124 <RowActions snippet={snippet} />
125 </>
126
127 export const TypeColumn: React.FC<ColumnProps> = ({ snippet }) => {
128 const { setCurrentType } = useSnippetsFilters()
129 const type = getSnippetType(snippet)
130
131 return (
132 <a
133 href={buildUrl(window.location.href, { type })}
134 onClick={event => {
135 event.preventDefault()
136 setCurrentType(type)
137 }}
138 >
139 <Badge name={type} />
140 </a>
141 )
142 }
143
144 export const TagsColumn: React.FC<ColumnProps> = ({ snippet }) =>
145 snippet.tags.map((tag, index) =>
146 <Fragment key={tag}>
147 <a key={tag} href={buildUrl(window.location.href, { tag })}>
148 {tag}
149 </a>
150 {index < snippet.tags.length - 1 ? ', ' : ''}
151 </Fragment>)
152
153 export const DateColumn: React.FC<ColumnProps> = ({ snippet }) =>
154 snippet.modified
155 ? <span className="modified-column-content" title={snippet.modified}>
156 <time dateTime={snippet.modified}>
157 {humanTimeDiff(snippet.modified, undefined)}
158 </time>
159 </span>
160 : <>&#8212;</>
161
162 const baseTableColumns: ListTableColumn<Snippet>[] = [
163 {
164 id: 'activate',
165 title: <span className="screen-reader-text">{__('Activate', 'code-snippets')}</span>,
166 render: snippet => <ActivateColumn snippet={snippet} />
167 },
168 {
169 id: 'name',
170 title: __('Name', 'code-snippets'),
171 isPrimary: true,
172 sortedValue: snippet => getSnippetDisplayName(snippet).toLowerCase(),
173 render: snippet => <NameColumn snippet={snippet} />
174 },
175 {
176 id: 'type',
177 title: __('Type', 'code-snippets'),
178 sortedValue: snippet => getSnippetType(snippet),
179 render: snippet => <TypeColumn snippet={snippet} />
180 },
181 {
182 id: 'desc',
183 title: __('Description', 'code-snippets'),
184 render: snippet => <div className="snippet-description-content"><RawHTML>{snippet.desc}</RawHTML></div>
185 },
186 {
187 id: 'tags',
188 title: __('Tags', 'code-snippets'),
189 render: snippet => <TagsColumn snippet={snippet} />
190 },
191 {
192 id: 'date',
193 title: __('Modified', 'code-snippets'),
194 sortedValue: snippet => snippet.modified ? new Date(snippet.modified).toISOString() : '',
195 render: snippet => <DateColumn snippet={snippet} />
196 },
197 {
198 id: 'priority',
199 title: __('Priority', 'code-snippets'),
200 sortedValue: snippet => snippet.priority,
201 render: snippet => <SnippetPriorityInput snippet={snippet} />
202 }
203 ]
204
205 export const getTableColumns = (hiddenColumns: Set<Key>): ListTableColumn<Snippet>[] =>
206 baseTableColumns.map(column => ({ ...column, isHidden: hiddenColumns.has(column.id) }))
207