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
code-snippets / js / components / ManageMenu / SnippetsTable / SnippetsTableControls.tsx

SnippetsTableControls.tsx in Code Snippets 4.0.0-beta.2, at js/components/ManageMenu/SnippetsTable/SnippetsTableControls.tsx

135 lines 4.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { __, _x, sprintf } from '@wordpress/i18n'
2 import React, { Fragment, useId, useMemo } from 'react'
3 import { useRestAPI } from '../../../hooks/useRestAPI'
4 import { useSnippetsList } from '../../../hooks/useSnippetsList'
5 import { handleUnknownError } from '../../../utils/errors'
6 import { REST_BASES } from '../../../utils/restAPI'
7 import { buildUrl } from '../../../utils/urls'
8 import { SubmitButton } from '../../common/SubmitButton'
9 import { SearchArea } from './SnippetsTableSearch'
10 import { useFilteredSnippets } from './WithFilteredSnippetsContext'
11 import { INDEX_STATUS, useSnippetsFilters } from './WithSnippetsTableFilters'
12 import type { Snippet } from '../../../types/Snippet'
13 import type { SnippetStatus } from './WithSnippetsTableFilters'
14
15 const STATUS_LABELS: [SnippetStatus, string][] = [
16 ['all', __('All', 'code-snippets')],
17 ['active', __('Active', 'code-snippets')],
18 ['inactive', __('Inactive', 'code-snippets')],
19 ['recently_active', __('Recently Active', 'code-snippets')],
20 ['locked', __('Locked', 'code-snippets')],
21 ['unlocked', __('Unlocked', 'code-snippets')],
22 ['trashed', __('Trashed', 'code-snippets')]
23 ]
24
25 const SnippetStatusCounts = () => {
26 const { currentStatus, setCurrentStatus } = useSnippetsFilters()
27 const { snippetsByStatus } = useFilteredSnippets()
28
29 const visibleStatuses = STATUS_LABELS.filter(([status]) =>
30 snippetsByStatus.has(status) && ('unlocked' !== status || snippetsByStatus.has('locked')))
31
32 return (
33 <ul className="subsubsub">
34 {visibleStatuses.map(([status, label]) =>
35 <Fragment key={status}>
36 <li className={status}>
37 <a
38 href={buildUrl(window.location.href, {
39 status: INDEX_STATUS === status ? undefined : status
40 })}
41 className={currentStatus === status ? 'current' : undefined}
42 aria-current={currentStatus === status ? 'page' : undefined}
43 onClick={event => {
44 event.preventDefault()
45 setCurrentStatus(status)
46 }}
47 >
48 {label} <span className="count">{
49 // translators: %d: number of snippets in the current view.
50 sprintf(_x('(%d)', 'table view count', 'code-snippets'), snippetsByStatus.get(status)?.length ?? 0)
51 }</span>
52 </a>
53 </li>
54 </Fragment>)}
55 </ul>
56 )
57 }
58
59 const ClearRecentlyActiveButton: React.FC = () => {
60 const { api } = useRestAPI()
61 const { refreshSnippetsList } = useSnippetsList()
62 const { currentStatus } = useSnippetsFilters()
63
64 return 'recently_active' === currentStatus
65 ? <div className="alignleft actions">
66 <SubmitButton
67 secondary
68 name="clear-recent-list"
69 text={__('Clear List', 'code-snippets')}
70 onClick={event => {
71 event.preventDefault()
72 api.del(REST_BASES.recentlyActive)
73 .then(refreshSnippetsList)
74 .catch(handleUnknownError)
75 }}
76 />
77 </div>
78 : null
79 }
80
81 interface FilterByTagControlProps {
82 visibleSnippets: Snippet[]
83 }
84
85 const FilterByTagControl: React.FC<FilterByTagControlProps> = ({ visibleSnippets }) => {
86 const { currentTag, setCurrentTag } = useSnippetsFilters()
87 const tagFilterId = useId()
88
89 const tagsList: Set<string> = useMemo(
90 () => visibleSnippets.reduce((tags, snippet) => {
91 snippet.tags.forEach(tag => tags.add(tag))
92 return tags
93 }, new Set<string>()),
94 [visibleSnippets])
95
96 return 0 < tagsList.size
97 ? <div className="alignleft actions">
98 <label htmlFor={tagFilterId} className="screen-reader-text">
99 {__('Filter snippets by tag', 'code-snippets')}
100 </label>
101 <select
102 id={tagFilterId}
103 name="tag"
104 value={currentTag}
105 aria-label={__('Filter snippets by tag', 'code-snippets')}
106 onChange={event => setCurrentTag(event.target.value)}
107 >
108 <option value="">{__('All Tags', 'code-snippets')}</option>
109 {[...tagsList].map(tag =>
110 <option key={tag} value={tag}>{tag}</option>)}
111 </select>
112 </div>
113 : null
114 }
115
116 export interface SnippetsTableNavigationProps {
117 which: 'top' | 'bottom'
118 visibleSnippets: Snippet[]
119 }
120
121 export const SnippetsTableNavigation: React.FC<SnippetsTableNavigationProps> = ({
122 which,
123 visibleSnippets
124 }) =>
125 <>
126 {'top' === which && <FilterByTagControl visibleSnippets={visibleSnippets} />}
127 <ClearRecentlyActiveButton />
128 {'top' === which && <SearchArea />}
129 </>
130
131 export const SnippetsTableToolbar = () =>
132 <div className="snippets-table-toolbar">
133 <SnippetStatusCounts />
134 </div>
135