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

CloudSnippetsTable.tsx in Code Snippets 3.10.0-beta.1, at js/components/ManageMenu/CommunityCloud/CloudSnippetsTable.tsx

150 lines 4.8 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 } 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 { CloudSnippetPreviewModal } from '../../common/cloud/CloudSnippetPreviewModal'
9 import { CloudStatusBadge } from '../../common/cloud/CloudStatusBadge'
10 import { useCloudSearch } from './WithCloudSearchContext'
11 import type { CloudSnippetSchema } from '../../../types/schema/CloudSnippetSchema'
12 import type { Dispatch, SetStateAction } from 'react'
13
14 type CloudSnippetId = CloudSnippetSchema['id']
15 type SetSelected = Dispatch<SetStateAction<Set<CloudSnippetId>>>
16
17 const updateSelection = (setSelected: SetSelected, ids: CloudSnippetId[], isSelected: boolean) => {
18 setSelected(previous => {
19 const updated = new Set(previous)
20 ids.forEach(id => isSelected ? updated.add(id) : updated.delete(id))
21 return updated
22 })
23 }
24
25 interface CloudSnippetRowProps {
26 snippet: CloudSnippetSchema
27 selected: Set<CloudSnippetId>
28 setSelected: SetSelected
29 }
30
31 interface CloudSnippetActionsProps extends Pick<CloudSnippetRowProps, 'snippet'> {
32 isPreviewOpen: boolean
33 setIsPreviewOpen: (isOpen: boolean) => void
34 }
35
36 const CloudSnippetActions: React.FC<CloudSnippetActionsProps> = ({
37 snippet,
38 isPreviewOpen,
39 setIsPreviewOpen
40 }) => {
41 const { doSearch } = useCloudSearch()
42
43 return (
44 <>
45 <div className="cloud-snippet-action-buttons">
46 <Button secondary onClick={() => setIsPreviewOpen(true)}>
47 {__('Preview', 'code-snippets')}
48 </Button>
49
50 <CloudSnippetDownloadButton snippet={snippet} onDownloaded={doSearch} />
51 </div>
52
53 <CloudSnippetPreviewModal
54 snippet={snippet}
55 isOpen={isPreviewOpen}
56 setIsOpen={setIsPreviewOpen}
57 onDownloaded={doSearch}
58 />
59 </>
60 )
61 }
62
63 const CloudSnippetRow: React.FC<CloudSnippetRowProps> = ({ snippet, selected, setSelected }) => {
64 const [isPreviewOpen, setIsPreviewOpen] = useState(false)
65
66 return (
67 <tr>
68 <th scope="row" className="check-column">
69 <input
70 id={`cb-select-${snippet.id}`}
71 type="checkbox"
72 name="checked[]"
73 checked={selected.has(snippet.id)}
74 aria-label={sprintf(
75 // translators: %s: snippet name.
76 __('Select %s', 'code-snippets'),
77 snippet.name
78 )}
79 onChange={event => updateSelection(setSelected, [snippet.id], event.target.checked)}
80 />
81 </th>
82
83 <td className="column-name column-primary">
84 <strong>
85 <button
86 type="button"
87 className="cloud-table-name-button"
88 title={__('Preview this snippet', 'code-snippets')}
89 onClick={() => setIsPreviewOpen(true)}
90 >
91 {snippet.name}
92 </button>
93 </strong>
94 </td>
95
96 <td className="column-type"><Badge name={getSnippetType(snippet)} /></td>
97
98 <td className="column-status"><CloudStatusBadge status={snippet.status} /></td>
99
100 <td className="column-desc">
101 <div className="cloud-table-description">{truncateChars(stripTags(snippet.description))}</div>
102 </td>
103
104 <td className="column-actions">
105 <CloudSnippetActions {...{ snippet, isPreviewOpen, setIsPreviewOpen }} />
106 </td>
107 </tr>
108 )
109 }
110
111 export interface CloudSnippetsTableProps {
112 snippets: CloudSnippetSchema[]
113 selected: Set<CloudSnippetId>
114 setSelected: SetSelected
115 }
116
117 /**
118 * Table view for lists of cloud snippets (community search results and
119 * bundle contents), mirroring the card actions. Descriptions are clamped
120 * so all rows stay the same height.
121 */
122 export const CloudSnippetsTable: React.FC<CloudSnippetsTableProps> = ({ snippets, selected, setSelected }) =>
123 <table className="wp-list-table widefat fixed striped cloud-snippets-table">
124 <thead>
125 <tr>
126 <td className="column-cb check-column">
127 <input
128 id="cb-select-all-cloud-snippets"
129 type="checkbox"
130 checked={0 < snippets.length && snippets.every(snippet => selected.has(snippet.id))}
131 aria-label={__('Select all snippets', 'code-snippets')}
132 onChange={event =>
133 updateSelection(setSelected, snippets.map(snippet => snippet.id), event.target.checked)}
134 />
135 </td>
136 <th scope="col" className="column-name column-primary">{__('Name', 'code-snippets')}</th>
137 <th scope="col" className="column-type">{__('Type', 'code-snippets')}</th>
138 <th scope="col" className="column-status">{__('Status', 'code-snippets')}</th>
139 <th scope="col" className="column-desc">{__('Description', 'code-snippets')}</th>
140 <th scope="col" className="column-actions">
141 <span className="screen-reader-text">{__('Actions', 'code-snippets')}</span>
142 </th>
143 </tr>
144 </thead>
145 <tbody>
146 {snippets.map(snippet =>
147 <CloudSnippetRow key={snippet.id} {...{ snippet, selected, setSelected }} />)}
148 </tbody>
149 </table>
150