base-js-sw 1.0.11 → 1.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/LinkPicker.js +164 -74
- package/package.json +1 -1
package/components/LinkPicker.js
CHANGED
|
@@ -106,6 +106,39 @@ const getResultStatus = (result) => {
|
|
|
106
106
|
).toLowerCase();
|
|
107
107
|
};
|
|
108
108
|
|
|
109
|
+
const getPostId = (value) => {
|
|
110
|
+
if (typeof value === 'number') {
|
|
111
|
+
return Number.isInteger(value) && value > 0 ? value : '';
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (typeof value !== 'string') {
|
|
115
|
+
return '';
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const trimmedValue = value.trim();
|
|
119
|
+
|
|
120
|
+
if (!/^\d+$/.test(trimmedValue)) {
|
|
121
|
+
return '';
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const numericValue = Number(trimmedValue);
|
|
125
|
+
|
|
126
|
+
return Number.isSafeInteger(numericValue) && numericValue > 0
|
|
127
|
+
? numericValue
|
|
128
|
+
: '';
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const isDirectUrlValue = ({ id, kind, type, url }) => {
|
|
132
|
+
const normalizedKind = String(kind || '').toLowerCase();
|
|
133
|
+
const normalizedType = String(type || '').toLowerCase();
|
|
134
|
+
|
|
135
|
+
return (
|
|
136
|
+
normalizedKind === 'url' ||
|
|
137
|
+
normalizedType === 'url' ||
|
|
138
|
+
(typeof id === 'string' && id === url)
|
|
139
|
+
);
|
|
140
|
+
};
|
|
141
|
+
|
|
109
142
|
const getLinkedPostStatusMessage = (result) => {
|
|
110
143
|
const status = getResultStatus(result);
|
|
111
144
|
|
|
@@ -151,84 +184,105 @@ const BrokenLinkBadge = ({ message }) => {
|
|
|
151
184
|
);
|
|
152
185
|
};
|
|
153
186
|
|
|
154
|
-
export const LinkPicker = ({
|
|
187
|
+
export const LinkPicker = ({
|
|
188
|
+
setAttributes,
|
|
189
|
+
at,
|
|
190
|
+
linkRef = 'link'
|
|
191
|
+
}) => {
|
|
192
|
+
|
|
155
193
|
const linkObj = at[linkRef] || {};
|
|
156
|
-
const { url, linkTarget, id } = linkObj;
|
|
157
|
-
const opensInNewTab = linkTarget === '_blank';
|
|
158
194
|
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
195
|
+
const {
|
|
196
|
+
url,
|
|
197
|
+
linkTarget,
|
|
198
|
+
id
|
|
199
|
+
} = linkObj;
|
|
162
200
|
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
result: null,
|
|
166
|
-
});
|
|
201
|
+
const opensInNewTab =
|
|
202
|
+
linkTarget === '_blank';
|
|
167
203
|
|
|
168
|
-
const
|
|
169
|
-
|
|
204
|
+
const initialPostId =
|
|
205
|
+
getPostId(id);
|
|
170
206
|
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
: 'External link';
|
|
207
|
+
const [localUrl, setLocalUrl] =
|
|
208
|
+
useState(url || '');
|
|
174
209
|
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
: '';
|
|
210
|
+
const [localId, setLocalId] =
|
|
211
|
+
useState(initialPostId);
|
|
178
212
|
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
|
|
213
|
+
const [localLinkTarget, setLocalLinkTarget] =
|
|
214
|
+
useState(opensInNewTab);
|
|
215
|
+
|
|
216
|
+
const [linkedPostStatus, setLinkedPostStatus] =
|
|
217
|
+
useState({
|
|
218
|
+
isLoading: false,
|
|
219
|
+
result: null,
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
const postId =
|
|
223
|
+
getPostId(localId);
|
|
224
|
+
|
|
225
|
+
const isInternalPost =
|
|
226
|
+
Boolean(postId);
|
|
227
|
+
|
|
228
|
+
const hasLinkData =
|
|
229
|
+
Boolean(localUrl || postId);
|
|
230
|
+
|
|
231
|
+
const statusLabel =
|
|
232
|
+
isInternalPost
|
|
233
|
+
? 'Dynamic WordPress link'
|
|
234
|
+
: 'External link';
|
|
235
|
+
|
|
236
|
+
const currentStatus =
|
|
237
|
+
linkedPostStatus.result
|
|
238
|
+
? getResultStatus(linkedPostStatus.result)
|
|
239
|
+
: '';
|
|
240
|
+
|
|
241
|
+
const brokenLinkMessage =
|
|
242
|
+
linkedPostStatus.result
|
|
243
|
+
? getLinkedPostStatusMessage(linkedPostStatus.result)
|
|
244
|
+
: '';
|
|
182
245
|
|
|
183
246
|
const shouldShowBrokenLinkStatus =
|
|
184
|
-
isInternalPost
|
|
185
|
-
linkedPostStatus.result
|
|
186
|
-
STATUSES.includes(currentStatus);
|
|
247
|
+
isInternalPost
|
|
248
|
+
&& linkedPostStatus.result
|
|
249
|
+
&& STATUSES.includes(currentStatus);
|
|
187
250
|
|
|
188
251
|
useEffect(() => {
|
|
189
|
-
setAttributes({
|
|
190
|
-
[linkRef]: {
|
|
191
|
-
url: localUrl
|
|
192
|
-
? encodeURI(safeDecodeURI(localUrl))
|
|
193
|
-
: '',
|
|
194
|
-
linkTarget: localLinkTarget
|
|
195
|
-
? '_blank'
|
|
196
|
-
: undefined,
|
|
197
|
-
id: localId
|
|
198
|
-
? localId
|
|
199
|
-
: undefined,
|
|
200
|
-
},
|
|
201
|
-
});
|
|
202
|
-
}, [localUrl, localId, localLinkTarget]);
|
|
203
252
|
|
|
204
|
-
|
|
205
|
-
|
|
253
|
+
const numericPostId =
|
|
254
|
+
getPostId(localId);
|
|
206
255
|
|
|
207
256
|
const hasValidPostId =
|
|
208
|
-
|
|
209
|
-
numericPostId > 0;
|
|
257
|
+
Boolean(numericPostId);
|
|
210
258
|
|
|
211
259
|
if (!hasValidPostId) {
|
|
260
|
+
|
|
212
261
|
setLinkedPostStatus({
|
|
213
262
|
isLoading: false,
|
|
214
263
|
result: null,
|
|
215
264
|
});
|
|
216
265
|
|
|
217
266
|
return;
|
|
267
|
+
|
|
218
268
|
}
|
|
219
269
|
|
|
220
270
|
if (linkedPostStatusCache[numericPostId]) {
|
|
271
|
+
|
|
221
272
|
setLinkedPostStatus({
|
|
222
273
|
isLoading: false,
|
|
223
274
|
result: linkedPostStatusCache[numericPostId],
|
|
224
275
|
});
|
|
225
276
|
|
|
226
277
|
return;
|
|
278
|
+
|
|
227
279
|
}
|
|
228
280
|
|
|
229
|
-
const apiFetch =
|
|
281
|
+
const apiFetch =
|
|
282
|
+
window.wp?.apiFetch;
|
|
230
283
|
|
|
231
284
|
if (!apiFetch) {
|
|
285
|
+
|
|
232
286
|
setLinkedPostStatus({
|
|
233
287
|
isLoading: false,
|
|
234
288
|
result: {
|
|
@@ -238,6 +292,7 @@ export const LinkPicker = ({ setAttributes, at, linkRef = 'link' }) => {
|
|
|
238
292
|
});
|
|
239
293
|
|
|
240
294
|
return;
|
|
295
|
+
|
|
241
296
|
}
|
|
242
297
|
|
|
243
298
|
let isMounted = true;
|
|
@@ -251,18 +306,22 @@ export const LinkPicker = ({ setAttributes, at, linkRef = 'link' }) => {
|
|
|
251
306
|
path: `/theme/v1/linked-post-validator/post/${numericPostId}`,
|
|
252
307
|
})
|
|
253
308
|
.then((result) => {
|
|
309
|
+
|
|
254
310
|
if (!isMounted) {
|
|
255
311
|
return;
|
|
256
312
|
}
|
|
257
313
|
|
|
258
|
-
linkedPostStatusCache[numericPostId] =
|
|
314
|
+
linkedPostStatusCache[numericPostId] =
|
|
315
|
+
result;
|
|
259
316
|
|
|
260
317
|
setLinkedPostStatus({
|
|
261
318
|
isLoading: false,
|
|
262
319
|
result,
|
|
263
320
|
});
|
|
321
|
+
|
|
264
322
|
})
|
|
265
323
|
.catch(() => {
|
|
324
|
+
|
|
266
325
|
if (!isMounted) {
|
|
267
326
|
return;
|
|
268
327
|
}
|
|
@@ -276,73 +335,99 @@ export const LinkPicker = ({ setAttributes, at, linkRef = 'link' }) => {
|
|
|
276
335
|
isLoading: false,
|
|
277
336
|
result: errorResult,
|
|
278
337
|
});
|
|
338
|
+
|
|
279
339
|
});
|
|
280
340
|
|
|
281
341
|
return () => {
|
|
282
342
|
isMounted = false;
|
|
283
343
|
};
|
|
344
|
+
|
|
284
345
|
}, [localId]);
|
|
285
346
|
|
|
286
|
-
const handleLinkChange = (updatedValue) => {
|
|
287
|
-
const { url, opensInNewTab, id } = updatedValue;
|
|
347
|
+
const handleLinkChange = (updatedValue = {}) => {
|
|
288
348
|
|
|
289
|
-
const
|
|
290
|
-
|
|
349
|
+
const {
|
|
350
|
+
url,
|
|
351
|
+
opensInNewTab,
|
|
352
|
+
id,
|
|
353
|
+
kind,
|
|
354
|
+
type,
|
|
355
|
+
} = updatedValue;
|
|
291
356
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
357
|
+
const nextUrl =
|
|
358
|
+
url || '';
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* When manually typing,
|
|
362
|
+
* Gutenberg keeps previous selected id.
|
|
363
|
+
*
|
|
364
|
+
* Manual typing has no kind/type.
|
|
365
|
+
*/
|
|
366
|
+
const isManualInput =
|
|
367
|
+
!kind
|
|
368
|
+
&& !type;
|
|
369
|
+
|
|
370
|
+
const nextPostId =
|
|
371
|
+
isManualInput
|
|
372
|
+
? undefined
|
|
373
|
+
: getPostId(id);
|
|
374
|
+
|
|
375
|
+
setLocalUrl(nextUrl);
|
|
376
|
+
|
|
377
|
+
setLocalId(
|
|
378
|
+
nextPostId || ''
|
|
379
|
+
);
|
|
380
|
+
|
|
381
|
+
setLocalLinkTarget(
|
|
382
|
+
Boolean(opensInNewTab)
|
|
383
|
+
);
|
|
384
|
+
|
|
385
|
+
setAttributes({
|
|
386
|
+
[linkRef]: {
|
|
387
|
+
url: nextUrl
|
|
388
|
+
? encodeURI(safeDecodeURI(nextUrl))
|
|
389
|
+
: '',
|
|
390
|
+
linkTarget: opensInNewTab
|
|
391
|
+
? '_blank'
|
|
392
|
+
: undefined,
|
|
393
|
+
id: nextPostId || undefined,
|
|
394
|
+
},
|
|
395
|
+
});
|
|
299
396
|
|
|
300
|
-
setLocalLinkTarget(Boolean(opensInNewTab));
|
|
301
397
|
};
|
|
302
398
|
|
|
303
399
|
return (
|
|
304
400
|
<div className="base-js-link-picker">
|
|
401
|
+
|
|
305
402
|
<style>{linkPickerStyles}</style>
|
|
306
403
|
|
|
307
404
|
<div className="base-js-link-picker__control">
|
|
405
|
+
|
|
308
406
|
<LinkControl
|
|
309
407
|
value={{
|
|
310
408
|
url: localUrl,
|
|
311
409
|
opensInNewTab: localLinkTarget,
|
|
312
|
-
id:
|
|
410
|
+
id: postId || undefined,
|
|
313
411
|
}}
|
|
314
412
|
onChange={(updatedValue) => {
|
|
315
413
|
handleLinkChange(updatedValue);
|
|
316
414
|
}}
|
|
317
|
-
onBlur={() => {
|
|
318
|
-
setAttributes({
|
|
319
|
-
[linkRef]: {
|
|
320
|
-
url: localId
|
|
321
|
-
? ''
|
|
322
|
-
: localUrl
|
|
323
|
-
? encodeURI(safeDecodeURI(localUrl))
|
|
324
|
-
: '',
|
|
325
|
-
linkTarget: localLinkTarget
|
|
326
|
-
? '_blank'
|
|
327
|
-
: undefined,
|
|
328
|
-
id: localId
|
|
329
|
-
? localId
|
|
330
|
-
: undefined,
|
|
331
|
-
},
|
|
332
|
-
});
|
|
333
|
-
}}
|
|
334
415
|
/>
|
|
416
|
+
|
|
335
417
|
</div>
|
|
336
418
|
|
|
337
419
|
{hasLinkData && (
|
|
338
420
|
<div className="base-js-link-picker__status-wrapper">
|
|
421
|
+
|
|
339
422
|
<div className="base-js-link-picker__status">
|
|
423
|
+
|
|
340
424
|
<Icon
|
|
341
425
|
icon={isInternalPost ? update : external}
|
|
342
426
|
size={18}
|
|
343
427
|
/>
|
|
344
428
|
|
|
345
429
|
<span>{statusLabel}</span>
|
|
430
|
+
|
|
346
431
|
</div>
|
|
347
432
|
|
|
348
433
|
{isInternalPost && linkedPostStatus.isLoading && (
|
|
@@ -353,13 +438,18 @@ export const LinkPicker = ({ setAttributes, at, linkRef = 'link' }) => {
|
|
|
353
438
|
|
|
354
439
|
{shouldShowBrokenLinkStatus && (
|
|
355
440
|
<div className="base-js-link-picker__status-detail">
|
|
441
|
+
|
|
356
442
|
<BrokenLinkBadge
|
|
357
443
|
message={brokenLinkMessage}
|
|
358
444
|
/>
|
|
445
|
+
|
|
359
446
|
</div>
|
|
360
447
|
)}
|
|
448
|
+
|
|
361
449
|
</div>
|
|
362
450
|
)}
|
|
451
|
+
|
|
363
452
|
</div>
|
|
364
453
|
);
|
|
454
|
+
|
|
365
455
|
};
|