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 / CommunityCloud / CloudSnippetsTable.tsx

CloudSnippetsTable.tsx in Code Snippets 3.10.2, at js/components/ManageMenu/CommunityCloud/CloudSnippetsTable.tsx

156 lines 5.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { __, sprintf } from '@wordpress/i18n'
2 import React, { useState } from 'react'
3 import { getSnippetType, isCloudSnippetDownloadable } from '../../../utils/snippets/snippets'
4 import { stripTags, truncateChars } from '../../../utils/text'
5 import { Badge } from '../../common/Badge'
6 import { Button } from '../../common/Button'
7 import { CloudSnippetDownloadButton } from '../../common/cloud/CloudSnippetDownloadButton'
8 import { CloudStatusBadge } from '../../common/cloud/CloudStatusBadge'
9 import { CloudSnippetPreviewModal } from '../../common/snippets/SnippetPreviewModal'
10 import { useCloudSearch } from './WithCloudSearchContext'
11 import type { CloudSnippetSchema } from '../../../types/schema/CloudSnippetSchema'
12 import type { Dispatch, SetStateAction } from 'react'
13
14 interface CloudSnippetRowProps {
15 snippet: CloudSnippetSchema
16 }
17
18 const CloudSnippetRow: React.FC<CloudSnippetRowProps> = ({ snippet }) => {
19 const { doSearch } = useCloudSearch()
20 const [isPreviewOpen, setIsPreviewOpen] = useState(false)
21
22 return (
23 <>
24 <td className="column-name column-primary">
25 <strong>
26 <button
27 type="button"
28 className="cloud-table-name-button"
29 title={__('Preview this snippet', 'code-snippets')}
30 onClick={() => setIsPreviewOpen(true)}
31 >
32 {snippet.name}
33 </button>
34 </strong>
35 </td>
36
37 <td className="column-type"><Badge name={getSnippetType(snippet)} /></td>
38
39 <td className="column-status"><CloudStatusBadge status={snippet.status} /></td>
40
41 <td className="column-desc">
42 <div className="cloud-table-description">{truncateChars(stripTags(snippet.description))}</div>
43 </td>
44
45 <td className="column-actions">
46 <div className="cloud-snippet-action-buttons">
47 <Button secondary onClick={() => setIsPreviewOpen(true)}>
48 {__('Preview', 'code-snippets')}
49 </Button>
50
51 <CloudSnippetDownloadButton snippet={snippet} onDownloaded={doSearch} />
52 </div>
53
54 {isPreviewOpen && (
55 <CloudSnippetPreviewModal snippet={snippet} setIsOpen={setIsPreviewOpen} onDownloaded={doSearch} />)}
56 </td>
57 </>
58 )
59 }
60
61 interface TableHeadingCheckboxProps {
62 availableIds: CloudSnippetSchema['id'][]
63 selectedIds: Set<CloudSnippetSchema['id']>
64 setSelectedIds: Dispatch<SetStateAction<Set<CloudSnippetSchema['id']>>>
65 }
66
67 const TableHeadingCheckbox: React.FC<TableHeadingCheckboxProps> = ({ availableIds, selectedIds, setSelectedIds }) =>
68 <td className="column-cb check-column">
69 <input
70 id="cb-select-all-cloud-snippets"
71 type="checkbox"
72 checked={availableIds.every(snippetId => selectedIds.has(snippetId))}
73 onChange={event =>
74 setSelectedIds(previous =>
75 new Set(event.target.checked
76 ? [...previous, ...availableIds]
77 : [...previous].filter(snippetId => !availableIds.includes(snippetId)))
78 )}
79 aria-label={__('Select all snippets', 'code-snippets')}
80 />
81 </td>
82
83 interface TableRowCheckboxProps {
84 snippet: CloudSnippetSchema
85 selected: Set<CloudSnippetSchema['id']>
86 setSelected: Dispatch<SetStateAction<Set<CloudSnippetSchema['id']>>>
87 }
88
89 const TableRowCheckbox: React.FC<TableRowCheckboxProps> = ({ snippet, selected, setSelected }) =>
90 <th scope="row" className="check-column">
91 {isCloudSnippetDownloadable(snippet) && (
92 <input
93 id={`cb-select-${snippet.id}`}
94 type="checkbox"
95 name="checked[]"
96 checked={selected.has(snippet.id)}
97 // translators: %s: snippet name.
98 aria-label={sprintf(__('Select %s', 'code-snippets'), snippet.name)}
99 onChange={event =>
100 setSelected(previous =>
101 new Set(event.target.checked
102 ? [...previous, snippet.id]
103 : [...previous].filter(snippetId => snippetId !== snippet.id))
104 )}
105 />)}
106 </th>
107
108 export interface CloudSnippetsTableProps {
109 snippets: CloudSnippetSchema[]
110 selected?: Set<CloudSnippetSchema['id']>
111 setSelected?: Dispatch<SetStateAction<Set<CloudSnippetSchema['id']>>>
112 }
113
114 /**
115 * Table view for lists of cloud snippets (community search results and
116 * bundle contents), mirroring the card actions. Descriptions are clamped
117 * so all rows stay the same height. Selection is only offered when the
118 * containing view provides selection state, as bundle contents have no
119 * bulk actions.
120 */
121 export const CloudSnippetsTable: React.FC<CloudSnippetsTableProps> = ({
122 snippets,
123 selected,
124 setSelected
125 }) =>
126 <table className="wp-list-table widefat fixed striped cloud-snippets-table">
127 <thead>
128 <tr>
129 {selected && setSelected && (
130 <TableHeadingCheckbox
131 selectedIds={selected}
132 setSelectedIds={setSelected}
133 availableIds={snippets
134 .filter(snippet => isCloudSnippetDownloadable(snippet))
135 .map(snippet => snippet.id)}
136 />)}
137
138 <th scope="col" className="column-name column-primary">{__('Name', 'code-snippets')}</th>
139 <th scope="col" className="column-type">{__('Type', 'code-snippets')}</th>
140 <th scope="col" className="column-status">{__('Status', 'code-snippets')}</th>
141 <th scope="col" className="column-desc">{__('Description', 'code-snippets')}</th>
142 <th scope="col" className="column-actions">
143 <span className="screen-reader-text">{__('Actions', 'code-snippets')}</span>
144 </th>
145 </tr>
146 </thead>
147 <tbody>
148 {snippets.map(snippet =>
149 <tr key={snippet.id}>
150 {selected && setSelected && <TableRowCheckbox {...{ snippet, selected, setSelected }} />}
151 <CloudSnippetRow snippet={snippet} />
152 </tr>
153 )}
154 </tbody>
155 </table>
156