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 / SnippetsTable / SnippetsTable.tsx

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

166 lines 5.4 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 { createInterpolateElement } from '@wordpress/element'
3 import React, { useCallback, useMemo } from 'react'
4 import classnames from 'classnames'
5 import { WithRestAPIContext } from '../../../hooks/useRestAPI'
6 import { useSnippetView } from '../../../hooks/useSnippetView'
7 import { WithSnippetsAPIContext } from '../../../hooks/useSnippetsAPI'
8 import { WithSnippetsListContext, useSnippetsList } from '../../../hooks/useSnippetsList'
9 import { SNIPPET_TYPES } from '../../../types/Snippet'
10 import { isLicensed } from '../../../utils/screen'
11 import { SNIPPET_TYPE_LABELS, getSnippetAddNewUrl, getSnippetType, isProType } from '../../../utils/snippets/snippets'
12 import { buildUrl } from '../../../utils/urls'
13 import { Badge } from '../../common/Badge'
14 import { Notice } from '../../common/Notice'
15 import { ScreenMetaSlot } from '../../common/ScreenMetaSlot'
16 import { UpsellPage } from '../../common/UpsellDialog'
17 import { WithSnippetsTableFilters, useSnippetsFilters } from './WithSnippetsTableFilters'
18 import { WithFilteredSnippetsContext } from './WithFilteredSnippetsContext'
19 import { SnippetsListTable } from './SnippetsListTable'
20 import type { SnippetType } from '../../../types/Snippet'
21
22 interface SnippetTypeTabProps {
23 type?: SnippetType
24 count?: number
25 }
26
27 const SnippetTypeTab: React.FC<SnippetTypeTabProps> = ({ type, count }) => {
28 const { currentType, setCurrentType } = useSnippetsFilters()
29 const tabName = type ?? 'all'
30
31 return (
32 <li>
33 <a
34 href={buildUrl(window.location.href, { type: tabName })}
35 className={classnames('snippet-type-link', `${tabName}-type-link`, {
36 'active-type': type === currentType,
37 'pro-locked-type': type && type !== currentType && !isLicensed() && isProType(type)
38 })}
39 aria-current={type === currentType ? 'page' : undefined}
40 onClick={event => {
41 event.preventDefault()
42 setCurrentType(type)
43 }}
44 >
45 {type && <Badge name={type} />}
46 <span className={classnames(`${tabName}-label`, 'snippet-type-name')}>
47 {type
48 ? SNIPPET_TYPE_LABELS[type]
49 : <>
50 <span className="snippet-type-name-full">{__('All Snippets', 'code-snippets')}</span>
51 <span className="snippet-type-name-short">{__('All', 'code-snippets')}</span>
52 </>}
53 </span>
54 {count && <span className="subnav-count">{count}</span>}
55 {type && isProType(type) && !isLicensed() && <span className="pro-chip">{__('Pro', 'code-snippets')}</span>}
56 </a>
57 </li>
58 )
59 }
60
61 const SafeModeNotice = () =>
62 window.CODE_SNIPPETS_MANAGE?.isSafeModeActive
63 ? <Notice type="error">
64 <p>
65 <strong>{__('Warning:', 'code-snippets')}</strong>{'\n'}
66 {__('Safe mode is active and snippets will not execute!', 'code-snippets')}{'\n'}
67
68 {createInterpolateElement(
69 __('Remove the <code>CODE_SNIPPETS_SAFE_MODE</code> constant from <code>wp-config.php</code> file to turn off safe mode.', 'code-snippets'),
70 {
71 code: <code />
72 }
73 )}{'\n'}
74
75 <a href="https://codesnippets.pro/doc/safe-mode" target="_blank" rel="noreferrer">
76 {__('Read more', 'code-snippets')}
77 </a>
78 </p>
79 </Notice>
80 : null
81
82 // Counts render immediately from the values localized with the page, then
83 // switch to live values derived from the snippets list once it has loaded.
84 const useSnippetTypeCounts = () => {
85 const { snippetsList } = useSnippetsList()
86
87 const countedSnippets = useMemo(
88 () => snippetsList?.filter(snippet => !snippet.trashed),
89 [snippetsList]
90 )
91
92 const typeCounts = useMemo(
93 () => countedSnippets?.reduce((counts, snippet) => {
94 const type = getSnippetType(snippet)
95 return counts.set(type, (counts.get(type) ?? 0) + 1)
96 }, new Map<SnippetType, number>()),
97 [countedSnippets]
98 )
99
100 const localized = window.CODE_SNIPPETS_MANAGE?.typeCounts
101
102 const getCount = useCallback(
103 (type?: SnippetType) => countedSnippets
104 ? type ? typeCounts?.get(type) ?? 0 : countedSnippets.length
105 : localized?.[type ?? 'all'],
106 [countedSnippets, typeCounts, localized]
107 )
108
109 return { getCount }
110 }
111
112 const SnippetsTableInner = () => {
113 const { snippetView, setSnippetView } = useSnippetView()
114 const { currentType } = useSnippetsFilters()
115 const { getCount } = useSnippetTypeCounts()
116
117 return (
118 <>
119 <nav
120 className="snippet-type-nav"
121 aria-label={__('Snippet types', 'code-snippets')}
122 >
123 <ul>
124 <SnippetTypeTab count={getCount()} />
125 {SNIPPET_TYPES.map(type =>
126 <SnippetTypeTab key={type} type={type} count={getCount(type)} />)}
127 </ul>
128 </nav>
129
130 <ScreenMetaSlot />
131
132 <div className="snippets-page-header">
133 <h1>{sprintf(
134 // translators: %s: label of the currently selected snippet type.
135 __('Local Snippets: %s', 'code-snippets'),
136 currentType ? SNIPPET_TYPE_LABELS[currentType] : __('All Snippets', 'code-snippets')
137 )}</h1>
138 <a href={getSnippetAddNewUrl(currentType)} className="button button-primary">
139 {__('Create new Snippet', 'code-snippets')}
140 </a>
141 </div>
142
143 <hr className="wp-header-end" />
144
145 <SafeModeNotice />
146
147 {currentType && !isLicensed() && isProType(currentType)
148 ? <UpsellPage />
149 : <WithFilteredSnippetsContext>
150 <SnippetsListTable snippetView={snippetView} setSnippetView={setSnippetView} />
151 </WithFilteredSnippetsContext>}
152 </>
153 )
154 }
155
156 export const SnippetsTable: React.FC = () =>
157 <WithRestAPIContext>
158 <WithSnippetsAPIContext>
159 <WithSnippetsListContext>
160 <WithSnippetsTableFilters>
161 <SnippetsTableInner />
162 </WithSnippetsTableFilters>
163 </WithSnippetsListContext>
164 </WithSnippetsAPIContext>
165 </WithRestAPIContext>
166