PluginProbe
Code Snippets / 3.10.0-beta.2
Code Snippets v3.10.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
code-snippets / js / components / ManageMenu / CommunityCloud / CloudSnippetsTable.tsx

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

158 lines 5.2 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 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 {isPreviewOpen && (
54 <CloudSnippetPreviewModal snippet={snippet} setIsOpen={setIsPreviewOpen} onDownloaded={doSearch} />)}
55 </>
56 )
57 }
58
59 const CloudSnippetRow: React.FC<CloudSnippetRowProps> = ({ snippet, selected, setSelected }) => {
60 const [isPreviewOpen, setIsPreviewOpen] = useState(false)
61
62 return (
63 <tr>
64 {selected && setSelected
65 ? <th scope="row" className="check-column">
66 {isCloudSnippetDownloadable(snippet) && <input
67 id={`cb-select-${snippet.id}`}
68 type="checkbox"
69 name="checked[]"
70 checked={selected.has(snippet.id)}
71 aria-label={sprintf(
72 // translators: %s: snippet name.
73 __('Select %s', 'code-snippets'),
74 snippet.name
75 )}
76 onChange={event => updateSelection(setSelected, [snippet.id], event.target.checked)}
77 />}
78 </th>
79 : null}
80
81 <td className="column-name column-primary">
82 <strong>
83 <button
84 type="button"
85 className="cloud-table-name-button"
86 title={__('Preview this snippet', 'code-snippets')}
87 onClick={() => setIsPreviewOpen(true)}
88 >
89 {snippet.name}
90 </button>
91 </strong>
92 </td>
93
94 <td className="column-type"><Badge name={getSnippetType(snippet)} /></td>
95
96 <td className="column-status"><CloudStatusBadge status={snippet.status} /></td>
97
98 <td className="column-desc">
99 <div className="cloud-table-description">{truncateChars(stripTags(snippet.description))}</div>
100 </td>
101
102 <td className="column-actions">
103 <CloudSnippetActions {...{ snippet, isPreviewOpen, setIsPreviewOpen }} />
104 </td>
105 </tr>
106 )
107 }
108
109 export interface CloudSnippetsTableProps {
110 snippets: CloudSnippetSchema[]
111 selected?: Set<CloudSnippetId>
112 setSelected?: SetSelected
113 }
114
115 /**
116 * Table view for lists of cloud snippets (community search results and
117 * bundle contents), mirroring the card actions. Descriptions are clamped
118 * so all rows stay the same height. Selection is only offered when the
119 * containing view provides selection state, as bundle contents have no
120 * bulk actions.
121 */
122 export const CloudSnippetsTable: React.FC<CloudSnippetsTableProps> = ({
123 snippets,
124 selected,
125 setSelected
126 }) => {
127 const downloadable = snippets.filter(snippet => isCloudSnippetDownloadable(snippet))
128
129 return <table className="wp-list-table widefat fixed striped cloud-snippets-table">
130 <thead>
131 <tr>
132 {selected && setSelected && (
133 <td className="column-cb check-column">
134 <input
135 id="cb-select-all-cloud-snippets"
136 type="checkbox"
137 checked={0 < downloadable.length && downloadable.every(snippet => selected.has(snippet.id))}
138 aria-label={__('Select all snippets', 'code-snippets')}
139 onChange={event =>
140 updateSelection(setSelected, downloadable.map(snippet => snippet.id), event.target.checked)}
141 />
142 </td>)}
143 <th scope="col" className="column-name column-primary">{__('Name', 'code-snippets')}</th>
144 <th scope="col" className="column-type">{__('Type', 'code-snippets')}</th>
145 <th scope="col" className="column-status">{__('Status', 'code-snippets')}</th>
146 <th scope="col" className="column-desc">{__('Description', 'code-snippets')}</th>
147 <th scope="col" className="column-actions">
148 <span className="screen-reader-text">{__('Actions', 'code-snippets')}</span>
149 </th>
150 </tr>
151 </thead>
152 <tbody>
153 {snippets.map(snippet =>
154 <CloudSnippetRow key={snippet.id} {...{ snippet, selected, setSelected }} />)}
155 </tbody>
156 </table>
157 }
158