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/CommunityCloud/CloudSnippetsTable.tsx +41 -10 3.10.2 → 4.0.0-beta.2 View file →
@@ -63,14 +63,21 @@
63 63 selectedIds: Set<CloudSnippetSchema['id']>
64 64 setSelectedIds: Dispatch<SetStateAction<Set<CloudSnippetSchema['id']>>>
65 65 }
66 66
67 +/**
68 + * Selects every snippet on the page that can be downloaded. With nothing
69 + * downloadable the box is disabled and unticked: "all of nothing" must not
70 + * read as a selection.
71 + */
67 72 const TableHeadingCheckbox: React.FC<TableHeadingCheckboxProps> = ({ availableIds, selectedIds, setSelectedIds }) =>
68 73 <td className="column-cb check-column">
69 74 <input
70 75 id="cb-select-all-cloud-snippets"
71 76 type="checkbox"
72 - checked={availableIds.every(snippetId => selectedIds.has(snippetId))}
77 + checked={0 < availableIds.length && availableIds.every(snippetId => selectedIds.has(snippetId))}
78 + disabled={0 === availableIds.length}
79 + title={0 === availableIds.length ? __('Nothing on this page can be downloaded.', 'code-snippets') : undefined}
73 80 onChange={event =>
74 81 setSelectedIds(previous =>
75 82 new Set(event.target.checked
76 83 ? [...previous, ...availableIds]
@@ -75,12 +82,23 @@
75 82 new Set(event.target.checked
76 83 ? [...previous, ...availableIds]
77 84 : [...previous].filter(snippetId => !availableIds.includes(snippetId)))
78 85 )}
79 - aria-label={__('Select all snippets', 'code-snippets')}
86 + aria-label={__('Select all downloadable snippets', 'code-snippets')}
80 87 />
81 88 </td>
82 89
90 +/** Why a snippet cannot be selected for download, or undefined when it can. */
91 +const unavailableReason = (snippet: CloudSnippetSchema): string | undefined => {
92 + if (snippet.local_id) {
93 + return __('Already in your library.', 'code-snippets')
94 + }
95 +
96 + return isCloudSnippetDownloadable(snippet)
97 + ? undefined
98 + : __('Requires Code Snippets Pro.', 'code-snippets')
99 +}
100 +
83 101 interface TableRowCheckboxProps {
84 102 snippet: CloudSnippetSchema
85 103 selected: Set<CloudSnippetSchema['id']>
86 104 setSelected: Dispatch<SetStateAction<Set<CloudSnippetSchema['id']>>>
@@ -85,18 +103,29 @@
85 103 selected: Set<CloudSnippetSchema['id']>
86 104 setSelected: Dispatch<SetStateAction<Set<CloudSnippetSchema['id']>>>
87 105 }
88 106
89 -const TableRowCheckbox: React.FC<TableRowCheckboxProps> = ({ snippet, selected, setSelected }) =>
90 - <th scope="row" className="check-column">
91 - {isCloudSnippetDownloadable(snippet) && (
107 +/**
108 + * Every row shows a box, so the column reads as one control: a snippet that
109 + * cannot be downloaded gets a disabled box that says why.
110 + */
111 +const TableRowCheckbox: React.FC<TableRowCheckboxProps> = ({ snippet, selected, setSelected }) => {
112 + const reason = unavailableReason(snippet)
113 +
114 + return (
115 + <th scope="row" className="check-column">
92 116 <input
93 117 id={`cb-select-${snippet.id}`}
94 118 type="checkbox"
95 119 name="checked[]"
96 - checked={selected.has(snippet.id)}
97 - // translators: %s: snippet name.
98 - aria-label={sprintf(__('Select %s', 'code-snippets'), snippet.name)}
120 + checked={!reason && selected.has(snippet.id)}
121 + disabled={!!reason}
122 + title={reason}
123 + aria-label={reason
124 + // translators: 1: snippet name, 2: why it cannot be selected.
125 + ? sprintf(__('%1$s cannot be selected: %2$s', 'code-snippets'), snippet.name, reason)
126 + // translators: %s: snippet name.
127 + : sprintf(__('Select %s', 'code-snippets'), snippet.name)}
99 128 onChange={event =>
100 129 setSelected(previous =>
101 130 new Set(event.target.checked
102 131 ? [...previous, snippet.id]
@@ -101,10 +130,12 @@
101 130 new Set(event.target.checked
102 131 ? [...previous, snippet.id]
103 132 : [...previous].filter(snippetId => snippetId !== snippet.id))
104 133 )}
105 - />)}
106 - </th>
134 + />
135 + </th>
136 + )
137 +}
107 138
108 139 export interface CloudSnippetsTableProps {
109 140 snippets: CloudSnippetSchema[]
110 141 selected?: Set<CloudSnippetSchema['id']>