PluginProbe
CryptX / 4.2.1
CryptX v4.2.1
4.2.1 4.2.0 4.1.1 trunk 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.9 2.0 2.1 2.2 2.3 2.3.1 2.3.2 2.3.3 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 All 93 releases
← All changes | src/components/App.js +52 -21 4.1.14.2.1 View file →
@@ -35,11 +35,24 @@
35 35
36 36 return known.includes( requested ) ? requested : tabs[ 0 ]?.id;
37 37 }
38 38
39 -export default function App() {
39 +export default function App( { scope = 'site' } ) {
40 + const isNetwork = scope === 'network';
41 +
42 + // One route or the other. Everything below is the same screen either way --
43 + // the network route hands back a schema without the two settings that mean
44 + // something different on every site, so there is no second field list here
45 + // that could fall behind the first.
46 + const route = isNetwork
47 + ? '/cryptx/v1/network-defaults'
48 + : '/cryptx/v1/settings';
49 +
40 50 const [ schema, setSchema ] = useState( null );
41 51 const [ values, setValues ] = useState( null );
52 + // Only used by the secrets card on the Advanced tab, and read once: a
53 + // rotation nobody meant to trigger is otherwise invisible.
54 + const [ rotatedAt, setRotatedAt ] = useState( '' );
42 55 const [ savedValues, setSavedValues ] = useState( null );
43 56 const [ activeTab, setActiveTab ] = useState( null );
44 57 const [ notice, setNotice ] = useState( null );
45 58 const [ isSaving, setSaving ] = useState( false );
@@ -46,13 +59,14 @@
46 59 const [ loadError, setLoadError ] = useState( null );
47 60 const [ confirmReset, setConfirmReset ] = useState( false );
48 61
49 62 useEffect( () => {
50 - apiFetch( { path: '/cryptx/v1/settings' } )
63 + apiFetch( { path: route } )
51 64 .then( ( response ) => {
52 65 setSchema( response.schema );
53 66 setValues( response.values );
54 67 setSavedValues( response.values );
68 + setRotatedAt( response.secretsRotatedAt || '' );
55 69 setActiveTab( tabFromLocation( response.schema.tabs ) );
56 70 } )
57 71 .catch( ( error ) => {
58 72 setLoadError(
@@ -59,9 +73,9 @@
59 73 error?.message ||
60 74 __( 'The settings could not be loaded.', 'cryptx' )
61 75 );
62 76 } );
63 - }, [] );
77 + }, [ route ] );
64 78
65 79 const isDirty = useMemo( () => {
66 80 if ( ! values || ! savedValues ) {
67 81 return false;
@@ -118,9 +132,9 @@
118 132 setSaving( true );
119 133 setNotice( null );
120 134
121 135 apiFetch( {
122 - path: '/cryptx/v1/settings',
136 + path: route,
123 137 method: 'POST',
124 138 data: { values },
125 139 } )
126 140 .then( ( response ) => {
@@ -136,9 +150,9 @@
136 150 __( 'The settings could not be saved.', 'cryptx' ),
137 151 } );
138 152 } )
139 153 .finally( () => setSaving( false ) );
140 - }, [ values ] );
154 + }, [ values, route ] );
141 155
142 156 const reset = useCallback( () => {
143 157 setConfirmReset( false );
144 158 setSaving( true );
@@ -193,14 +207,23 @@
193 207
194 208 return (
195 209 <div className="cryptx-settings">
196 210 <header className="cryptx-settings__header">
197 - <h1>{ __( 'CryptX', 'cryptx' ) }</h1>
211 + <h1>
212 + { isNetwork
213 + ? __( 'CryptX network defaults', 'cryptx' )
214 + : __( 'CryptX', 'cryptx' ) }
215 + </h1>
198 216 <p className="cryptx-settings__intro">
199 - { __(
200 - 'CryptX hides email addresses in your pages from spam bots while keeping them usable for your visitors.',
201 - 'cryptx'
202 - ) }
217 + { isNetwork
218 + ? __(
219 + 'What a newly created site starts with. Sites that already exist are never changed by this — every site keeps its own settings, and a site administrator can change theirs at any time. Two settings are missing here on purpose: excluded posts and the uploaded image refer to things that exist on one site only. One deserves a second look before you set it: an address on the list under Exceptions is left readable, and a network default puts it on every site created from now on.',
220 + 'cryptx'
221 + )
222 + : __(
223 + 'CryptX hides email addresses in your pages from spam bots while keeping them usable for your visitors.',
224 + 'cryptx'
225 + ) }
203 226 </p>
204 227 </header>
205 228
206 229 <Tabs tabs={ tabs } active={ current.id } onSelect={ selectTab } />
@@ -226,8 +249,10 @@
226 249 tab={ current.id }
227 250 fields={ schema.fields }
228 251 values={ values }
229 252 onChange={ setValue }
253 + rotatedAt={ rotatedAt }
254 + isNetwork={ isNetwork }
230 255 />
231 256 ) }
232 257 </main>
233 258
@@ -249,19 +274,25 @@
249 274 >
250 275 { __( 'Save changes', 'cryptx' ) }
251 276 </Button>
252 277 </FlexItem>
253 - <FlexItem>
254 - <Button
255 - variant="tertiary"
256 - isDestructive
257 - onClick={ () => setConfirmReset( true ) }
258 - disabled={ isSaving }
259 - __next40pxDefaultSize
260 - >
261 - { __( 'Restore defaults', 'cryptx' ) }
262 - </Button>
263 - </FlexItem>
278 + { /* Only on the site screen: this route resets the
279 + settings of one site, which is not what a network
280 + administrator looking at the defaults would
281 + expect it to mean. */ }
282 + { ! isNetwork && (
283 + <FlexItem>
284 + <Button
285 + variant="tertiary"
286 + isDestructive
287 + onClick={ () => setConfirmReset( true ) }
288 + disabled={ isSaving }
289 + __next40pxDefaultSize
290 + >
291 + { __( 'Restore defaults', 'cryptx' ) }
292 + </Button>
293 + </FlexItem>
294 + ) }
264 295 </Flex>
265 296 { /* The state is said in words as well as shown by the
266 297 button, because a disabled button on its own reads as
267 298 "broken" rather than as "nothing to do". */ }