@pixelated-tech/components 3.4.3 → 3.5.0
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/README.md +12 -191
- package/dist/components/admin/componentusage/componentAnalysis.js +12 -4
- package/dist/components/admin/componentusage/componentDiscovery.js +20 -6
- package/dist/components/admin/site-health/site-health-accessibility.js +5 -1
- package/dist/components/admin/site-health/site-health-axe-core.js +4 -0
- package/dist/components/admin/site-health/site-health-cloudwatch.integration.js +0 -5
- package/dist/components/admin/site-health/site-health-cloudwatch.js +7 -1
- package/dist/components/admin/site-health/site-health-dependency-vulnerabilities.js +4 -0
- package/dist/components/admin/site-health/site-health-github.js +6 -0
- package/dist/components/admin/site-health/site-health-google-analytics.js +6 -0
- package/dist/components/admin/site-health/site-health-google-search-console.js +6 -0
- package/dist/components/admin/site-health/site-health-on-site-seo.integration.js +128 -55
- package/dist/components/admin/site-health/site-health-on-site-seo.js +4 -0
- package/dist/components/admin/site-health/site-health-overview.js +11 -4
- package/dist/components/admin/site-health/site-health-performance.js +4 -0
- package/dist/components/admin/site-health/site-health-security.js +5 -1
- package/dist/components/admin/site-health/site-health-seo.js +5 -1
- package/dist/components/admin/site-health/site-health-template.js +19 -9
- package/dist/components/admin/site-health/site-health-uptime.js +4 -0
- package/dist/components/callout/callout.js +0 -10
- package/dist/components/carousel/carousel.js +15 -4
- package/dist/components/carousel/tiles.js +1 -1
- package/dist/components/cms/contentful.items.components.js +3 -4
- package/dist/components/cms/flickr.js +1 -1
- package/dist/components/cms/google.reviews.components.js +3 -3
- package/dist/components/cms/instagram.components.js +15 -5
- package/dist/components/cms/smartimage.js +2 -2
- package/dist/components/cms/wordpress.components.js +32 -6
- package/dist/components/cms/yelp.js +5 -0
- package/dist/components/config/config.server.js +7 -1
- package/dist/components/general/css.js +0 -1
- package/dist/components/general/image.js +0 -1
- package/dist/components/general/loading.js +2 -1
- package/dist/components/general/microinteractions.js +0 -1
- package/dist/components/general/modal.css +2 -4
- package/dist/components/general/modal.js +72 -30
- package/dist/components/general/sidepanel.js +16 -0
- package/dist/components/general/tab.js +1 -0
- package/dist/components/menu/menu-accordion.css +1 -1
- package/dist/components/menu/menu-accordion.js +15 -4
- package/dist/components/menu/menu-expando.js +21 -19
- package/dist/components/menu/menu-simple.js +14 -14
- package/dist/components/nerdjoke/nerdjoke.js +1 -1
- package/dist/components/seo/googlesearch.js +0 -1
- package/dist/components/seo/schema-blogposting.js +6 -1
- package/dist/components/seo/schema-recipe.js +34 -1
- package/dist/components/seo/schema-services.js +20 -2
- package/dist/components/shoppingcart/ebay.components.js +3 -3
- package/dist/components/shoppingcart/shoppingcart.components.js +76 -28
- package/dist/components/shoppingcart/shoppingcart.functions.js +4 -4
- package/dist/components/sitebuilder/config/CompoundFontSelector.js +13 -4
- package/dist/components/sitebuilder/config/ConfigBuilder.css +194 -5
- package/dist/components/sitebuilder/config/ConfigBuilder.js +183 -17
- package/dist/components/sitebuilder/config/FontSelector.js +13 -2
- package/dist/components/sitebuilder/config/routes-form.json +67 -0
- package/dist/components/sitebuilder/config/siteinfo-form.json +28 -14
- package/dist/components/sitebuilder/config/visualdesignform.json +4 -4
- package/dist/components/sitebuilder/form/formbuilder.js +1 -0
- package/dist/components/sitebuilder/form/formcomponents.js +2 -3
- package/dist/components/sitebuilder/form/formengine.js +6 -5
- package/dist/components/sitebuilder/form/formvalidator.js +5 -0
- package/dist/components/sitebuilder/page/components/PageBuilderUI.js +5 -1
- package/dist/components/structured/buzzwordbingo.css +0 -1
- package/dist/components/structured/recipe.js +1 -1
- package/dist/components/structured/socialcard.js +2 -2
- package/dist/components/utilities/functions.js +82 -1
- package/dist/components/utilities/gemini-api.client.js +76 -0
- package/dist/components/utilities/gemini-api.server.js +185 -0
- package/dist/data/routes.json +5 -5
- package/dist/index.adminclient.js +30 -0
- package/dist/index.adminserver.js +21 -0
- package/dist/index.js +4 -18
- package/dist/index.server.js +15 -28
- package/dist/types/components/admin/componentusage/componentAnalysis.d.ts.map +1 -1
- package/dist/types/components/admin/componentusage/componentDiscovery.d.ts +1 -1
- package/dist/types/components/admin/componentusage/componentDiscovery.d.ts.map +1 -1
- package/dist/types/components/admin/site-health/site-health-accessibility.d.ts +7 -4
- package/dist/types/components/admin/site-health/site-health-accessibility.d.ts.map +1 -1
- package/dist/types/components/admin/site-health/site-health-axe-core.d.ts +7 -4
- package/dist/types/components/admin/site-health/site-health-axe-core.d.ts.map +1 -1
- package/dist/types/components/admin/site-health/site-health-cloudwatch.d.ts +9 -6
- package/dist/types/components/admin/site-health/site-health-cloudwatch.d.ts.map +1 -1
- package/dist/types/components/admin/site-health/site-health-cloudwatch.integration.d.ts.map +1 -1
- package/dist/types/components/admin/site-health/site-health-dependency-vulnerabilities.d.ts +7 -4
- package/dist/types/components/admin/site-health/site-health-dependency-vulnerabilities.d.ts.map +1 -1
- package/dist/types/components/admin/site-health/site-health-github.d.ts +9 -6
- package/dist/types/components/admin/site-health/site-health-github.d.ts.map +1 -1
- package/dist/types/components/admin/site-health/site-health-google-analytics.d.ts +9 -6
- package/dist/types/components/admin/site-health/site-health-google-analytics.d.ts.map +1 -1
- package/dist/types/components/admin/site-health/site-health-google-search-console.d.ts +9 -6
- package/dist/types/components/admin/site-health/site-health-google-search-console.d.ts.map +1 -1
- package/dist/types/components/admin/site-health/site-health-on-site-seo.d.ts +8 -3
- package/dist/types/components/admin/site-health/site-health-on-site-seo.d.ts.map +1 -1
- package/dist/types/components/admin/site-health/site-health-on-site-seo.integration.d.ts.map +1 -1
- package/dist/types/components/admin/site-health/site-health-overview.d.ts +7 -4
- package/dist/types/components/admin/site-health/site-health-overview.d.ts.map +1 -1
- package/dist/types/components/admin/site-health/site-health-performance.d.ts +7 -4
- package/dist/types/components/admin/site-health/site-health-performance.d.ts.map +1 -1
- package/dist/types/components/admin/site-health/site-health-security.d.ts +7 -4
- package/dist/types/components/admin/site-health/site-health-security.d.ts.map +1 -1
- package/dist/types/components/admin/site-health/site-health-seo.d.ts +7 -4
- package/dist/types/components/admin/site-health/site-health-seo.d.ts.map +1 -1
- package/dist/types/components/admin/site-health/site-health-template.d.ts +12 -10
- package/dist/types/components/admin/site-health/site-health-template.d.ts.map +1 -1
- package/dist/types/components/admin/site-health/site-health-uptime.d.ts +7 -4
- package/dist/types/components/admin/site-health/site-health-uptime.d.ts.map +1 -1
- package/dist/types/components/callout/callout.d.ts +3 -3
- package/dist/types/components/callout/callout.d.ts.map +1 -1
- package/dist/types/components/carousel/carousel.d.ts +16 -7
- package/dist/types/components/carousel/carousel.d.ts.map +1 -1
- package/dist/types/components/carousel/tiles.d.ts +3 -6
- package/dist/types/components/carousel/tiles.d.ts.map +1 -1
- package/dist/types/components/cms/flickr.d.ts +3 -6
- package/dist/types/components/cms/flickr.d.ts.map +1 -1
- package/dist/types/components/cms/google.reviews.components.d.ts +1 -7
- package/dist/types/components/cms/google.reviews.components.d.ts.map +1 -1
- package/dist/types/components/cms/hubspot.components.d.ts +1 -2
- package/dist/types/components/cms/hubspot.components.d.ts.map +1 -1
- package/dist/types/components/cms/instagram.components.d.ts +14 -9
- package/dist/types/components/cms/instagram.components.d.ts.map +1 -1
- package/dist/types/components/cms/smartimage.d.ts +2 -28
- package/dist/types/components/cms/smartimage.d.ts.map +1 -1
- package/dist/types/components/cms/wordpress.components.d.ts +33 -14
- package/dist/types/components/cms/wordpress.components.d.ts.map +1 -1
- package/dist/types/components/cms/yelp.d.ts +9 -4
- package/dist/types/components/cms/yelp.d.ts.map +1 -1
- package/dist/types/components/config/config.server.d.ts +9 -6
- package/dist/types/components/config/config.server.d.ts.map +1 -1
- package/dist/types/components/general/loading.d.ts +5 -1
- package/dist/types/components/general/loading.d.ts.map +1 -1
- package/dist/types/components/general/microinteractions.d.ts +1 -3
- package/dist/types/components/general/microinteractions.d.ts.map +1 -1
- package/dist/types/components/general/modal.d.ts +11 -5
- package/dist/types/components/general/modal.d.ts.map +1 -1
- package/dist/types/components/general/semantic.d.ts +3 -3
- package/dist/types/components/general/sidepanel.d.ts +20 -13
- package/dist/types/components/general/sidepanel.d.ts.map +1 -1
- package/dist/types/components/general/tab.d.ts +1 -2
- package/dist/types/components/general/tab.d.ts.map +1 -1
- package/dist/types/components/menu/menu-accordion.d.ts +22 -9
- package/dist/types/components/menu/menu-accordion.d.ts.map +1 -1
- package/dist/types/components/menu/menu-expando.d.ts +14 -5
- package/dist/types/components/menu/menu-expando.d.ts.map +1 -1
- package/dist/types/components/menu/menu-simple.d.ts +4 -5
- package/dist/types/components/menu/menu-simple.d.ts.map +1 -1
- package/dist/types/components/nerdjoke/nerdjoke.d.ts +1 -1
- package/dist/types/components/nerdjoke/nerdjoke.d.ts.map +1 -1
- package/dist/types/components/seo/googleanalytics.d.ts.map +1 -1
- package/dist/types/components/seo/metadata.components.d.ts +2 -2
- package/dist/types/components/seo/metadata.components.d.ts.map +1 -1
- package/dist/types/components/seo/schema-blogposting.d.ts +7 -4
- package/dist/types/components/seo/schema-blogposting.d.ts.map +1 -1
- package/dist/types/components/seo/schema-recipe.d.ts +29 -30
- package/dist/types/components/seo/schema-recipe.d.ts.map +1 -1
- package/dist/types/components/seo/schema-services.d.ts +19 -9
- package/dist/types/components/seo/schema-services.d.ts.map +1 -1
- package/dist/types/components/shoppingcart/paypal.d.ts +1 -1
- package/dist/types/components/shoppingcart/paypal.d.ts.map +1 -1
- package/dist/types/components/shoppingcart/shoppingcart.components.d.ts +77 -28
- package/dist/types/components/shoppingcart/shoppingcart.components.d.ts.map +1 -1
- package/dist/types/components/shoppingcart/shoppingcart.functions.d.ts +4 -23
- package/dist/types/components/shoppingcart/shoppingcart.functions.d.ts.map +1 -1
- package/dist/types/components/sitebuilder/config/CompoundFontSelector.d.ts +10 -11
- package/dist/types/components/sitebuilder/config/CompoundFontSelector.d.ts.map +1 -1
- package/dist/types/components/sitebuilder/config/ConfigBuilder.d.ts +41 -174
- package/dist/types/components/sitebuilder/config/ConfigBuilder.d.ts.map +1 -1
- package/dist/types/components/sitebuilder/config/FontSelector.d.ts +12 -13
- package/dist/types/components/sitebuilder/config/FontSelector.d.ts.map +1 -1
- package/dist/types/components/sitebuilder/form/formbuilder.d.ts +7 -3
- package/dist/types/components/sitebuilder/form/formbuilder.d.ts.map +1 -1
- package/dist/types/components/sitebuilder/form/formcomponents.d.ts +1 -1
- package/dist/types/components/sitebuilder/form/formcomponents.d.ts.map +1 -1
- package/dist/types/components/sitebuilder/form/formengine.d.ts +1 -2
- package/dist/types/components/sitebuilder/form/formengine.d.ts.map +1 -1
- package/dist/types/components/sitebuilder/form/formextractor.d.ts +5 -4
- package/dist/types/components/sitebuilder/form/formextractor.d.ts.map +1 -1
- package/dist/types/components/sitebuilder/form/formtypes.d.ts +3 -3
- package/dist/types/components/sitebuilder/form/formtypes.d.ts.map +1 -1
- package/dist/types/components/sitebuilder/form/formvalidator.d.ts +8 -3
- package/dist/types/components/sitebuilder/form/formvalidator.d.ts.map +1 -1
- package/dist/types/components/sitebuilder/page/components/ComponentPropertiesForm.d.ts +2 -3
- package/dist/types/components/sitebuilder/page/components/ComponentPropertiesForm.d.ts.map +1 -1
- package/dist/types/components/sitebuilder/page/components/ComponentSelector.d.ts +2 -3
- package/dist/types/components/sitebuilder/page/components/ComponentSelector.d.ts.map +1 -1
- package/dist/types/components/sitebuilder/page/components/ComponentTree.d.ts +2 -3
- package/dist/types/components/sitebuilder/page/components/ComponentTree.d.ts.map +1 -1
- package/dist/types/components/sitebuilder/page/components/PageBuilderUI.d.ts +8 -7
- package/dist/types/components/sitebuilder/page/components/PageBuilderUI.d.ts.map +1 -1
- package/dist/types/components/sitebuilder/page/components/PageEngine.d.ts.map +1 -1
- package/dist/types/components/sitebuilder/page/components/SaveLoadSection.d.ts +2 -3
- package/dist/types/components/sitebuilder/page/components/SaveLoadSection.d.ts.map +1 -1
- package/dist/types/components/sitebuilder/page/lib/componentMap.d.ts +1 -1
- package/dist/types/components/structured/markdown.d.ts +1 -3
- package/dist/types/components/structured/markdown.d.ts.map +1 -1
- package/dist/types/components/structured/recipe.d.ts +5 -32
- package/dist/types/components/structured/recipe.d.ts.map +1 -1
- package/dist/types/components/structured/socialcard.d.ts +4 -0
- package/dist/types/components/structured/socialcard.d.ts.map +1 -1
- package/dist/types/components/structured/timeline.d.ts +1 -3
- package/dist/types/components/structured/timeline.d.ts.map +1 -1
- package/dist/types/components/utilities/functions.d.ts +20 -0
- package/dist/types/components/utilities/functions.d.ts.map +1 -1
- package/dist/types/components/utilities/gemini-api.client.d.ts +38 -0
- package/dist/types/components/utilities/gemini-api.client.d.ts.map +1 -0
- package/dist/types/components/utilities/gemini-api.server.d.ts +17 -0
- package/dist/types/components/utilities/gemini-api.server.d.ts.map +1 -0
- package/dist/types/index.adminclient.d.ts +27 -0
- package/dist/types/index.adminclient.d.ts.map +1 -0
- package/dist/types/index.adminserver.d.ts +19 -0
- package/dist/types/index.adminserver.d.ts.map +1 -0
- package/dist/types/index.d.ts +4 -18
- package/dist/types/index.server.d.ts +5 -28
- package/dist/types/stories/general/sidepanel.stories.d.ts.map +1 -1
- package/dist/types/stories/general/smartimage.stories.d.ts +74 -2
- package/dist/types/stories/general/smartimage.stories.d.ts.map +1 -1
- package/package.json +19 -9
- package/README.COMPONENTS.md +0 -2310
- package/dist/components/cms/pixelated.linkedin.js +0 -180
- package/dist/components/cms/pixelated.linkedin1.js +0 -84
- package/dist/components/cms/pixelated.linkedin2.js +0 -92
- package/dist/types/components/cms/pixelated.linkedin.d.ts +0 -2
- package/dist/types/components/cms/pixelated.linkedin.d.ts.map +0 -1
- package/dist/types/components/cms/pixelated.linkedin1.d.ts +0 -2
- package/dist/types/components/cms/pixelated.linkedin1.d.ts.map +0 -1
- package/dist/types/components/cms/pixelated.linkedin2.d.ts +0 -2
- package/dist/types/components/cms/pixelated.linkedin2.d.ts.map +0 -1
- package/dist/types/tests/pixelated.menu-expando.test.d.ts +0 -2
- package/dist/types/tests/pixelated.menu-expando.test.d.ts.map +0 -1
|
@@ -361,36 +361,62 @@ function calculateFacetedNavigationScore(data) {
|
|
|
361
361
|
/**
|
|
362
362
|
* Browser Caching Data Collector
|
|
363
363
|
*/
|
|
364
|
-
function collectBrowserCachingData(
|
|
365
|
-
// Get response headers from Puppeteer response object
|
|
366
|
-
const headers = {};
|
|
364
|
+
async function collectBrowserCachingData(url) {
|
|
367
365
|
try {
|
|
368
|
-
const
|
|
369
|
-
|
|
370
|
-
headers
|
|
366
|
+
const response = await fetch(url, {
|
|
367
|
+
method: 'HEAD', // Use HEAD to get headers without downloading the full content
|
|
368
|
+
headers: {
|
|
369
|
+
'User-Agent': 'Mozilla/5.0 (compatible; SEO Analysis Bot)'
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
if (!response.ok) {
|
|
373
|
+
return {
|
|
374
|
+
cacheControl: '',
|
|
375
|
+
expires: '',
|
|
376
|
+
lastModified: '',
|
|
377
|
+
etag: '',
|
|
378
|
+
age: '',
|
|
379
|
+
hasCachingHeaders: false,
|
|
380
|
+
error: `HTTP ${response.status}: ${response.statusText}`
|
|
381
|
+
};
|
|
371
382
|
}
|
|
383
|
+
const cacheControl = response.headers.get('cache-control') || '';
|
|
384
|
+
const expires = response.headers.get('expires') || '';
|
|
385
|
+
const lastModified = response.headers.get('last-modified') || '';
|
|
386
|
+
const etag = response.headers.get('etag') || '';
|
|
387
|
+
const age = response.headers.get('age') || '';
|
|
388
|
+
return {
|
|
389
|
+
cacheControl,
|
|
390
|
+
expires,
|
|
391
|
+
lastModified,
|
|
392
|
+
etag,
|
|
393
|
+
age,
|
|
394
|
+
hasCachingHeaders: !!(cacheControl || expires || lastModified || etag)
|
|
395
|
+
};
|
|
372
396
|
}
|
|
373
|
-
catch
|
|
374
|
-
|
|
397
|
+
catch {
|
|
398
|
+
return {
|
|
399
|
+
cacheControl: '',
|
|
400
|
+
expires: '',
|
|
401
|
+
lastModified: '',
|
|
402
|
+
etag: '',
|
|
403
|
+
age: '',
|
|
404
|
+
hasCachingHeaders: false,
|
|
405
|
+
error: 'Could not access response headers - network error or server unavailable'
|
|
406
|
+
};
|
|
375
407
|
}
|
|
376
|
-
const cacheControl = headers['cache-control'] || '';
|
|
377
|
-
const expires = headers['expires'] || '';
|
|
378
|
-
const lastModified = headers['last-modified'] || '';
|
|
379
|
-
const etag = headers['etag'] || '';
|
|
380
|
-
const age = headers['age'] || '';
|
|
381
|
-
return {
|
|
382
|
-
cacheControl,
|
|
383
|
-
expires,
|
|
384
|
-
lastModified,
|
|
385
|
-
etag,
|
|
386
|
-
age,
|
|
387
|
-
hasCachingHeaders: !!(cacheControl || expires || lastModified || etag)
|
|
388
|
-
};
|
|
389
408
|
}
|
|
390
409
|
/**
|
|
391
410
|
* Browser Caching Scorer
|
|
392
411
|
*/
|
|
393
412
|
function calculateBrowserCachingScore(data) {
|
|
413
|
+
if (data.error) {
|
|
414
|
+
return {
|
|
415
|
+
score: 0,
|
|
416
|
+
displayValue: 'Requires server header analysis',
|
|
417
|
+
details: { error: data.error }
|
|
418
|
+
};
|
|
419
|
+
}
|
|
394
420
|
let score = 0;
|
|
395
421
|
let displayValue = 'No caching headers detected';
|
|
396
422
|
const issues = [];
|
|
@@ -448,32 +474,55 @@ function calculateBrowserCachingScore(data) {
|
|
|
448
474
|
/**
|
|
449
475
|
* Gzip Compression Data Collector
|
|
450
476
|
*/
|
|
451
|
-
function collectGzipCompressionData(
|
|
452
|
-
// Get response headers from Puppeteer response object
|
|
453
|
-
const headers = {};
|
|
477
|
+
async function collectGzipCompressionData(url) {
|
|
454
478
|
try {
|
|
455
|
-
const
|
|
456
|
-
|
|
457
|
-
headers
|
|
479
|
+
const response = await fetch(url, {
|
|
480
|
+
method: 'GET', // Changed from HEAD to GET to properly detect compression
|
|
481
|
+
headers: {
|
|
482
|
+
'User-Agent': 'Mozilla/5.0 (compatible; SEO Analysis Bot)',
|
|
483
|
+
'Accept-Encoding': 'gzip, deflate' // Added Accept-Encoding like browsers
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
if (!response.ok) {
|
|
487
|
+
return {
|
|
488
|
+
contentEncoding: '',
|
|
489
|
+
contentLength: '',
|
|
490
|
+
transferEncoding: '',
|
|
491
|
+
isCompressed: false,
|
|
492
|
+
error: `HTTP ${response.status}: ${response.statusText}`
|
|
493
|
+
};
|
|
458
494
|
}
|
|
495
|
+
const contentEncoding = response.headers.get('content-encoding') || '';
|
|
496
|
+
const contentLength = response.headers.get('content-length') || '';
|
|
497
|
+
const transferEncoding = response.headers.get('transfer-encoding') || '';
|
|
498
|
+
return {
|
|
499
|
+
contentEncoding,
|
|
500
|
+
contentLength,
|
|
501
|
+
transferEncoding,
|
|
502
|
+
isCompressed: contentEncoding.includes('gzip') || contentEncoding.includes('deflate')
|
|
503
|
+
};
|
|
459
504
|
}
|
|
460
|
-
catch
|
|
461
|
-
|
|
505
|
+
catch {
|
|
506
|
+
return {
|
|
507
|
+
contentEncoding: '',
|
|
508
|
+
contentLength: '',
|
|
509
|
+
transferEncoding: '',
|
|
510
|
+
isCompressed: false,
|
|
511
|
+
error: 'Could not access response headers - network error or server unavailable'
|
|
512
|
+
};
|
|
462
513
|
}
|
|
463
|
-
const contentEncoding = headers['content-encoding'] || '';
|
|
464
|
-
const contentLength = headers['content-length'] || '';
|
|
465
|
-
const transferEncoding = headers['transfer-encoding'] || '';
|
|
466
|
-
return {
|
|
467
|
-
contentEncoding,
|
|
468
|
-
contentLength,
|
|
469
|
-
transferEncoding,
|
|
470
|
-
isCompressed: contentEncoding.includes('gzip') || contentEncoding.includes('deflate') || transferEncoding.includes('chunked')
|
|
471
|
-
};
|
|
472
514
|
}
|
|
473
515
|
/**
|
|
474
516
|
* Gzip Compression Scorer
|
|
475
517
|
*/
|
|
476
518
|
function calculateGzipCompressionScore(data) {
|
|
519
|
+
if (data.error) {
|
|
520
|
+
return {
|
|
521
|
+
score: 0,
|
|
522
|
+
displayValue: 'Requires server header analysis',
|
|
523
|
+
details: { error: data.error }
|
|
524
|
+
};
|
|
525
|
+
}
|
|
477
526
|
let score = 0;
|
|
478
527
|
let displayValue = 'No compression detected';
|
|
479
528
|
if (data.isCompressed) {
|
|
@@ -614,11 +663,16 @@ async function analyzeSinglePage(url) {
|
|
|
614
663
|
// Navigate to the page with faster waiting strategy
|
|
615
664
|
const response = await page.goto(url, {
|
|
616
665
|
waitUntil: 'domcontentloaded', // Wait for DOM instead of all network requests
|
|
617
|
-
timeout:
|
|
666
|
+
timeout: 10000 // Reduced timeout from 15000 to 10000
|
|
618
667
|
});
|
|
668
|
+
// Check if navigation failed
|
|
669
|
+
if (!response) {
|
|
670
|
+
console.warn(`Failed to load page: ${url} - no response received`);
|
|
671
|
+
// Continue with analysis using available data, but mark header-dependent metrics as unavailable
|
|
672
|
+
}
|
|
619
673
|
// Wait for H1 elements to be rendered (if any) with a short timeout
|
|
620
674
|
try {
|
|
621
|
-
await page.waitForSelector('h1', { timeout:
|
|
675
|
+
await page.waitForSelector('h1', { timeout: 1000 }); // Reduced from 2000 to 1000
|
|
622
676
|
}
|
|
623
677
|
catch {
|
|
624
678
|
// H1 not found within timeout, continue anyway
|
|
@@ -639,7 +693,8 @@ async function analyzeSinglePage(url) {
|
|
|
639
693
|
});
|
|
640
694
|
// Get the rendered HTML for other pattern-based checks
|
|
641
695
|
const html = await page.content();
|
|
642
|
-
|
|
696
|
+
// Don't close the page here - let it be reused or closed by caller
|
|
697
|
+
// await page.close();
|
|
643
698
|
const audits = [];
|
|
644
699
|
// Process on-page metrics from configuration
|
|
645
700
|
const config = seoMetricsConfig;
|
|
@@ -653,10 +708,14 @@ async function analyzeSinglePage(url) {
|
|
|
653
708
|
const collector = dataCollectors[metric.dataCollector];
|
|
654
709
|
const scorer = scorers[metric.scorer];
|
|
655
710
|
if (collector && scorer) {
|
|
656
|
-
// Pass
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
711
|
+
// Pass URL for collectors that need headers (like browser caching and gzip compression)
|
|
712
|
+
let rawData;
|
|
713
|
+
if (metric.dataCollector === 'collectBrowserCachingData' || metric.dataCollector === 'collectGzipCompressionData') {
|
|
714
|
+
rawData = await collector(url);
|
|
715
|
+
}
|
|
716
|
+
else {
|
|
717
|
+
rawData = collector(html, pageData.title);
|
|
718
|
+
}
|
|
660
719
|
const result = scorer(rawData);
|
|
661
720
|
score = result.score;
|
|
662
721
|
displayValue = result.displayValue;
|
|
@@ -700,6 +759,8 @@ async function analyzeSinglePage(url) {
|
|
|
700
759
|
details
|
|
701
760
|
});
|
|
702
761
|
}
|
|
762
|
+
// Close the page after analysis
|
|
763
|
+
await page.close();
|
|
703
764
|
return {
|
|
704
765
|
url,
|
|
705
766
|
title: pageData.title,
|
|
@@ -719,11 +780,7 @@ async function analyzeSinglePage(url) {
|
|
|
719
780
|
crawledAt: new Date().toISOString()
|
|
720
781
|
};
|
|
721
782
|
}
|
|
722
|
-
|
|
723
|
-
if (browser) {
|
|
724
|
-
await browser.close();
|
|
725
|
-
}
|
|
726
|
-
}
|
|
783
|
+
// Don't close browser here - keep it alive for reuse
|
|
727
784
|
}
|
|
728
785
|
async function performSiteWideAudits(baseUrl) {
|
|
729
786
|
const audits = [];
|
|
@@ -799,12 +856,28 @@ async function performSiteWideAudits(baseUrl) {
|
|
|
799
856
|
}
|
|
800
857
|
break;
|
|
801
858
|
case 'gzip-compression':
|
|
802
|
-
|
|
803
|
-
|
|
859
|
+
try {
|
|
860
|
+
const gzipData = await collectGzipCompressionData(baseUrl);
|
|
861
|
+
const gzipResult = calculateGzipCompressionScore(gzipData);
|
|
862
|
+
score = gzipResult.score;
|
|
863
|
+
displayValue = gzipResult.displayValue;
|
|
864
|
+
}
|
|
865
|
+
catch {
|
|
866
|
+
score = 0;
|
|
867
|
+
displayValue = 'Error analyzing compression headers';
|
|
868
|
+
}
|
|
804
869
|
break;
|
|
805
870
|
case 'browser-caching':
|
|
806
|
-
|
|
807
|
-
|
|
871
|
+
try {
|
|
872
|
+
const cachingData = await collectBrowserCachingData(baseUrl);
|
|
873
|
+
const cachingResult = calculateBrowserCachingScore(cachingData);
|
|
874
|
+
score = cachingResult.score;
|
|
875
|
+
displayValue = cachingResult.displayValue;
|
|
876
|
+
}
|
|
877
|
+
catch {
|
|
878
|
+
score = 0;
|
|
879
|
+
displayValue = 'Error analyzing caching headers';
|
|
880
|
+
}
|
|
808
881
|
break;
|
|
809
882
|
case 'duplicate-content-detection':
|
|
810
883
|
score = 0; // Placeholder - would need multi-page content analysis
|
|
@@ -889,7 +962,7 @@ export async function performOnSiteSEOAnalysis(baseUrl) {
|
|
|
889
962
|
}
|
|
890
963
|
else {
|
|
891
964
|
// Fallback to crawling if sitemap not available
|
|
892
|
-
pagesToAnalyze = await crawlSite(baseUrl,
|
|
965
|
+
pagesToAnalyze = await crawlSite(baseUrl, 2); // Reduced from 5 to 2 pages
|
|
893
966
|
}
|
|
894
967
|
if (pagesToAnalyze.length === 0) {
|
|
895
968
|
return {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import PropTypes from 'prop-types';
|
|
3
4
|
import { SiteHealthTemplate } from './site-health-template';
|
|
4
5
|
import { getScoreIndicator } from './site-health-indicators';
|
|
5
6
|
/**
|
|
@@ -91,6 +92,9 @@ async function fetchOnSiteSEOData(siteName) {
|
|
|
91
92
|
};
|
|
92
93
|
}
|
|
93
94
|
}
|
|
95
|
+
SiteHealthOnSiteSEO.propTypes = {
|
|
96
|
+
siteName: PropTypes.string.isRequired,
|
|
97
|
+
};
|
|
94
98
|
export function SiteHealthOnSiteSEO({ siteName }) {
|
|
95
99
|
return (_jsx(SiteHealthTemplate, { siteName: siteName, title: "On-Site SEO", fetchData: fetchOnSiteSEOData, children: (data) => {
|
|
96
100
|
if (!data)
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useCallback } from 'react';
|
|
4
|
+
import PropTypes from 'prop-types';
|
|
4
5
|
import { SiteHealthTemplate } from './site-health-template';
|
|
5
6
|
import { getScoreIndicator } from './site-health-indicators';
|
|
7
|
+
SiteHealthOverview.propTypes = {
|
|
8
|
+
siteName: PropTypes.string.isRequired,
|
|
9
|
+
};
|
|
6
10
|
export function SiteHealthOverview({ siteName }) {
|
|
7
11
|
const fetchCWVData = useCallback(async (site) => {
|
|
8
12
|
const response = await fetch(`/api/site-health/core-web-vitals?siteName=${encodeURIComponent(site)}`);
|
|
@@ -57,9 +61,12 @@ export function SiteHealthOverview({ siteName }) {
|
|
|
57
61
|
};
|
|
58
62
|
return (_jsxs(_Fragment, { children: [_jsx("h4", { className: "health-site-name", children: siteData.site.replace('-', ' ') }), _jsxs("p", { className: "health-site-url", children: ["URL: ", siteData.url] }), _jsx("div", { className: "health-score-container", children: Object.entries(siteData.scores)
|
|
59
63
|
.filter(([, score]) => score !== null)
|
|
60
|
-
.map(([category, score]) =>
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
+
.map(([category, score]) => {
|
|
65
|
+
const numScore = score;
|
|
66
|
+
return (_jsxs("div", { className: "health-score-item", children: [_jsx("div", { className: "health-score-label", children: category.replace('-', ' ') }), _jsx("div", { className: "health-score-value", style: { color: getScoreColor(numScore) }, children: formatScore(numScore) }), _jsx("div", { className: "health-score-bar", children: _jsx("div", { className: "health-score-fill", style: {
|
|
67
|
+
width: numScore !== null ? `${numScore * 100}%` : '0%',
|
|
68
|
+
backgroundColor: numScore !== null ? getScoreColor(numScore) : '#6b7280'
|
|
69
|
+
} }) })] }, category));
|
|
70
|
+
}) }), _jsxs("div", { style: { marginBottom: '1.5rem' }, children: [_jsx("h5", { style: { fontSize: '1rem', fontWeight: '600', marginBottom: '1rem' }, children: "Core Web Vitals" }), _jsxs("div", { className: "health-cwv-grid", children: [_jsxs("div", { className: "health-cwv-item", children: [_jsx("span", { className: "health-cwv-label", children: "Cumulative Layout Shift:" }), _jsx("span", { className: "health-cwv-value", style: { color: getStatusColor(getMetricStatus(siteData.metrics.cls, { good: 0.1, poor: 0.25 })) }, children: formatMetric(siteData.metrics.cls, '') })] }), _jsxs("div", { className: "health-cwv-item", children: [_jsx("span", { className: "health-cwv-label", children: "First Input Delay:" }), _jsx("span", { className: "health-cwv-value", style: { color: getStatusColor(getMetricStatus(siteData.metrics.fid, { good: 100, poor: 300 })) }, children: formatMetric(siteData.metrics.fid, 'ms') })] }), _jsxs("div", { className: "health-cwv-item", children: [_jsx("span", { className: "health-cwv-label", children: "Largest Contentful Paint:" }), _jsx("span", { className: "health-cwv-value", style: { color: getStatusColor(getMetricStatus(siteData.metrics.lcp, { good: 2500, poor: 4000 })) }, children: formatMetric(siteData.metrics.lcp, 'ms') })] }), _jsxs("div", { className: "health-cwv-item", children: [_jsx("span", { className: "health-cwv-label", children: "First Contentful Paint:" }), _jsx("span", { className: "health-cwv-value", style: { color: getStatusColor(getMetricStatus(siteData.metrics.fcp, { good: 1800, poor: 3000 })) }, children: formatMetric(siteData.metrics.fcp, 'ms') })] }), _jsxs("div", { className: "health-cwv-item", children: [_jsx("span", { className: "health-cwv-label", children: "Time to First Byte:" }), _jsx("span", { className: "health-cwv-value", style: { color: getStatusColor(getMetricStatus(siteData.metrics.ttfb, { good: 800, poor: 1800 })) }, children: formatMetric(siteData.metrics.ttfb, 'ms') })] }), _jsxs("div", { className: "health-cwv-item", children: [_jsx("span", { className: "health-cwv-label", children: "Speed Index:" }), _jsx("span", { className: "health-cwv-value", style: { color: getStatusColor(getMetricStatus(siteData.metrics.speedIndex, { good: 3400, poor: 5800 })) }, children: formatMetric(siteData.metrics.speedIndex, 'ms') })] }), _jsxs("div", { className: "health-cwv-item", children: [_jsx("span", { className: "health-cwv-label", children: "Time to Interactive:" }), _jsx("span", { className: "health-cwv-value", style: { color: getStatusColor(getMetricStatus(siteData.metrics.interactive, { good: 3800, poor: 7300 })) }, children: formatMetric(siteData.metrics.interactive, 'ms') })] }), _jsxs("div", { className: "health-cwv-item", children: [_jsx("span", { className: "health-cwv-label", children: "Total Blocking Time:" }), _jsx("span", { className: "health-cwv-value", style: { color: getStatusColor(getMetricStatus(siteData.metrics.totalBlockingTime, { good: 200, poor: 600 })) }, children: formatMetric(siteData.metrics.totalBlockingTime, 'ms') })] }), _jsxs("div", { className: "health-cwv-item", children: [_jsx("span", { className: "health-cwv-label", children: "First Meaningful Paint:" }), _jsx("span", { className: "health-cwv-value", style: { color: getStatusColor(getMetricStatus(siteData.metrics.firstMeaningfulPaint, { good: 2000, poor: 4000 })) }, children: formatMetric(siteData.metrics.firstMeaningfulPaint, 'ms') })] })] })] }), _jsxs("p", { className: "health-timestamp", children: ["Last checked: ", new Date(siteData.timestamp).toLocaleString()] })] }));
|
|
64
71
|
} }));
|
|
65
72
|
}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useCallback } from 'react';
|
|
4
|
+
import PropTypes from 'prop-types';
|
|
4
5
|
import { SiteHealthTemplate } from './site-health-template';
|
|
5
6
|
import { getScoreIndicator } from './site-health-indicators';
|
|
7
|
+
SiteHealthPerformance.propTypes = {
|
|
8
|
+
siteName: PropTypes.string.isRequired,
|
|
9
|
+
};
|
|
6
10
|
export function SiteHealthPerformance({ siteName }) {
|
|
7
11
|
const fetchCWVData = useCallback(async (site) => {
|
|
8
12
|
const response = await fetch(`/api/site-health/core-web-vitals?siteName=${encodeURIComponent(site)}`);
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useCallback } from 'react';
|
|
4
|
+
import PropTypes from 'prop-types';
|
|
4
5
|
import { SiteHealthTemplate } from './site-health-template';
|
|
5
6
|
import { getScoreIndicator } from './site-health-indicators';
|
|
7
|
+
SiteHealthSecurity.propTypes = {
|
|
8
|
+
siteName: PropTypes.string.isRequired,
|
|
9
|
+
};
|
|
6
10
|
export function SiteHealthSecurity({ siteName }) {
|
|
7
11
|
const fetchSecurityData = useCallback(async (site) => {
|
|
8
12
|
// Fetch PSI data for best practices security audits
|
|
@@ -161,7 +165,7 @@ export function SiteHealthSecurity({ siteName }) {
|
|
|
161
165
|
width: `${(psiData.scores['best-practices'] || 0) * 100}%`,
|
|
162
166
|
backgroundColor: getScoreColor(psiData.scores['best-practices'])
|
|
163
167
|
} }) })] }) })), psiData.categories['best-practices'] && psiData.categories['best-practices'].audits.length > 0 && (_jsxs("div", { children: [_jsx("h5", { style: { fontSize: '1rem', fontWeight: '600', marginBottom: '1rem' }, children: "Security Best Practices" }), _jsx("div", { className: "space-y-2", children: psiData.categories['best-practices'].audits
|
|
164
|
-
.filter(audit => audit.scoreDisplayMode !== 'notApplicable')
|
|
168
|
+
.filter((audit) => audit.scoreDisplayMode !== 'notApplicable')
|
|
165
169
|
.sort((a, b) => (b.score || 0) - (a.score || 0))
|
|
166
170
|
.slice(0, 20)
|
|
167
171
|
.map((audit) => (_jsxs("div", { className: "health-audit-item", children: [_jsx("span", { className: "health-audit-icon", children: getAuditScoreIcon(audit.score) }), _jsxs("div", { className: "health-audit-content", children: [_jsxs("span", { className: "health-audit-title", children: ["(", Math.round((audit.score || 0) * 100), "%) ", audit.title] }), audit.displayValue && (_jsx("p", { className: "health-audit-description", children: audit.displayValue })), audit.details?.items && Array.isArray(audit.details.items) && audit.details.items.length > 0 && (audit.score || 0) < 0.9 && (_jsx("div", { className: "health-audit-details", children: _jsx("div", { style: { fontSize: '0.75rem', color: '#6b7280', marginTop: '0.25rem' }, children: audit.details.items.map((item, idx) => (_jsx("div", { style: { marginBottom: '0.125rem' }, children: formatAuditItem(item, audit.title) }, idx))) }) }))] })] }, audit.id))) })] })), _jsxs("p", { className: "health-timestamp", children: ["Last checked: ", new Date(psiData.timestamp).toLocaleString()] })] }));
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useCallback } from 'react';
|
|
4
|
+
import PropTypes from 'prop-types';
|
|
4
5
|
import { SiteHealthTemplate } from './site-health-template';
|
|
5
6
|
import { getScoreIndicator } from './site-health-indicators';
|
|
7
|
+
SiteHealthSEO.propTypes = {
|
|
8
|
+
siteName: PropTypes.string.isRequired,
|
|
9
|
+
};
|
|
6
10
|
export function SiteHealthSEO({ siteName }) {
|
|
7
11
|
const fetchSEOData = useCallback(async (site) => {
|
|
8
12
|
const response = await fetch(`/api/site-health/core-web-vitals?siteName=${encodeURIComponent(site)}`);
|
|
@@ -116,7 +120,7 @@ export function SiteHealthSEO({ siteName }) {
|
|
|
116
120
|
width: `${(siteData.scores.seo || 0) * 100}%`,
|
|
117
121
|
backgroundColor: getScoreColor(siteData.scores.seo)
|
|
118
122
|
} }) })] }) })), siteData.categories.seo && siteData.categories.seo.audits.length > 0 && (_jsxs("div", { children: [_jsx("h5", { style: { fontSize: '1rem', fontWeight: '600', marginBottom: '1rem' }, children: "SEO Issues & Recommendations" }), _jsx("div", { className: "space-y-2", children: siteData.categories.seo.audits
|
|
119
|
-
.filter(audit => audit.scoreDisplayMode !== 'notApplicable')
|
|
123
|
+
.filter((audit) => audit.scoreDisplayMode !== 'notApplicable')
|
|
120
124
|
.sort((a, b) => (b.score || 0) - (a.score || 0))
|
|
121
125
|
.slice(0, 20)
|
|
122
126
|
.map((audit) => (_jsxs("div", { className: "health-audit-item", children: [_jsx("span", { className: "health-audit-icon", children: getAuditScoreIcon(audit.score) }), _jsxs("div", { className: "health-audit-content", children: [_jsxs("span", { className: "health-audit-title", children: ["(", Math.round((audit.score || 0) * 100), "%) ", audit.title] }), audit.displayValue && (_jsx("p", { className: "health-audit-description", children: audit.displayValue })), audit.details?.items && Array.isArray(audit.details.items) && audit.details.items.length > 0 && (audit.score || 0) < 1.0 && (_jsx("div", { className: "health-audit-details", children: _jsx("div", { style: { fontSize: '0.75rem', color: '#6b7280', marginTop: '0.25rem' }, children: audit.details.items.map((item, idx) => (_jsx("div", { style: { marginBottom: '0.125rem' }, children: formatAuditItem(item, audit.title) }, idx))) }) }))] })] }, audit.id))) })] })), _jsxs("p", { className: "health-timestamp", children: ["Last checked: ", new Date(siteData.timestamp).toLocaleString()] })] }));
|
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useState } from 'react';
|
|
4
|
+
import PropTypes from 'prop-types';
|
|
4
5
|
import { PageGridItem } from '../../general/semantic';
|
|
5
|
-
|
|
6
|
+
SiteHealthTemplate.propTypes = {
|
|
7
|
+
siteName: PropTypes.string.isRequired,
|
|
8
|
+
title: PropTypes.string,
|
|
9
|
+
children: PropTypes.func.isRequired,
|
|
10
|
+
fetchData: PropTypes.func.isRequired,
|
|
11
|
+
enableCacheControl: PropTypes.bool,
|
|
12
|
+
columnSpan: PropTypes.number,
|
|
13
|
+
};
|
|
14
|
+
export function SiteHealthTemplate(props) {
|
|
15
|
+
const typedProps = props;
|
|
6
16
|
const [data, setData] = useState(null);
|
|
7
17
|
const [loading, setLoading] = useState(false);
|
|
8
18
|
const [error, setError] = useState(null);
|
|
9
19
|
useEffect(() => {
|
|
10
20
|
let isMounted = true;
|
|
11
21
|
const loadData = async () => {
|
|
12
|
-
if (!siteName) {
|
|
22
|
+
if (!typedProps.siteName) {
|
|
13
23
|
if (isMounted) {
|
|
14
24
|
setData(null);
|
|
15
25
|
setLoading(false);
|
|
@@ -25,8 +35,8 @@ export function SiteHealthTemplate({ siteName, title, children, fetchData, enabl
|
|
|
25
35
|
// Check for cache control from URL query parameters
|
|
26
36
|
const urlParams = new URLSearchParams(window.location.search);
|
|
27
37
|
const cacheParam = urlParams.get('cache');
|
|
28
|
-
const useCache = enableCacheControl ? (cacheParam !== 'false') : true;
|
|
29
|
-
const result = await fetchData(siteName, useCache);
|
|
38
|
+
const useCache = typedProps.enableCacheControl ? (cacheParam !== 'false') : true;
|
|
39
|
+
const result = await typedProps.fetchData(typedProps.siteName, useCache);
|
|
30
40
|
if (isMounted) {
|
|
31
41
|
setData(result);
|
|
32
42
|
setError(null);
|
|
@@ -48,15 +58,15 @@ export function SiteHealthTemplate({ siteName, title, children, fetchData, enabl
|
|
|
48
58
|
return () => {
|
|
49
59
|
isMounted = false;
|
|
50
60
|
};
|
|
51
|
-
}, [siteName, fetchData]);
|
|
61
|
+
}, [typedProps.siteName, typedProps.fetchData]);
|
|
52
62
|
// If no site selected, show nothing
|
|
53
|
-
if (!siteName) {
|
|
63
|
+
if (!typedProps.siteName) {
|
|
54
64
|
return null;
|
|
55
65
|
}
|
|
56
66
|
// If title is provided, render the complete card structure
|
|
57
|
-
if (title) {
|
|
58
|
-
return (_jsxs(PageGridItem, { className: "health-card", columnSpan: columnSpan, children: [_jsx("h2", { className: "health-card-title", children: title }), _jsx("div", { className: "health-card-content", children: loading ? (_jsxs("div", { className: "health-loading", children: [_jsx("div", { className: "health-loading-spinner" }), _jsx("p", { className: "health-loading-text", children: "Loading..." })] })) : error ? (_jsx("div", { className: "health-error", children: _jsxs("p", { className: "health-error-text", children: ["Error: ", error] }) })) : (children(data)) })] }));
|
|
67
|
+
if (typedProps.title) {
|
|
68
|
+
return (_jsxs(PageGridItem, { className: "health-card", columnSpan: typedProps.columnSpan, children: [_jsx("h2", { className: "health-card-title", children: typedProps.title }), _jsx("div", { className: "health-card-content", children: loading ? (_jsxs("div", { className: "health-loading", children: [_jsx("div", { className: "health-loading-spinner" }), _jsx("p", { className: "health-loading-text", children: "Loading..." })] })) : error ? (_jsx("div", { className: "health-error", children: _jsxs("p", { className: "health-error-text", children: ["Error: ", error] }) })) : (typedProps.children(data)) })] }));
|
|
59
69
|
}
|
|
60
70
|
// Legacy mode: render content directly without wrapper
|
|
61
|
-
return (_jsx(_Fragment, { children: loading ? (_jsxs("div", { className: "health-loading", children: [_jsx("div", { className: "health-loading-spinner" }), _jsx("p", { className: "health-loading-text", children: "Loading..." })] })) : error ? (_jsx("div", { className: "health-error", children: _jsxs("p", { className: "health-error-text", children: ["Error: ", error] }) })) : (children(data)) }));
|
|
71
|
+
return (_jsx(_Fragment, { children: loading ? (_jsxs("div", { className: "health-loading", children: [_jsx("div", { className: "health-loading-spinner" }), _jsx("p", { className: "health-loading-text", children: "Loading..." })] })) : error ? (_jsx("div", { className: "health-error", children: _jsxs("p", { className: "health-error-text", children: ["Error: ", error] }) })) : (typedProps.children(data)) }));
|
|
62
72
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import PropTypes from 'prop-types';
|
|
3
4
|
import { SiteHealthTemplate } from './site-health-template';
|
|
5
|
+
SiteHealthUptime.propTypes = {
|
|
6
|
+
siteName: PropTypes.string.isRequired,
|
|
7
|
+
};
|
|
4
8
|
export function SiteHealthUptime({ siteName }) {
|
|
5
9
|
const fetchUptimeData = async (site) => {
|
|
6
10
|
const response = await fetch(`/api/site-health/uptime?siteName=${encodeURIComponent(site)}`);
|
|
@@ -89,16 +89,6 @@ CalloutButton.propTypes = {
|
|
|
89
89
|
url: PropTypes.string.isRequired,
|
|
90
90
|
target: PropTypes.string
|
|
91
91
|
};
|
|
92
|
-
/* export function CalloutButton( { title, url, target } : CalloutButtonType) {
|
|
93
|
-
return (
|
|
94
|
-
<div className="callout-button">
|
|
95
|
-
{ (url)
|
|
96
|
-
? <button type="button" className="callout-button"><a href={url || ""} target={target || ""} rel={target=="_blank" ? "noopener noreferrer" : ""}>{title}</a></button>
|
|
97
|
-
: null
|
|
98
|
-
}
|
|
99
|
-
</div>
|
|
100
|
-
);
|
|
101
|
-
} */
|
|
102
92
|
export function CalloutButton({ title, url, target }) {
|
|
103
93
|
const handleClick = () => {
|
|
104
94
|
if (target === '_blank') {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useState, useEffect, useRef } from 'react';
|
|
4
|
-
import PropTypes
|
|
4
|
+
import PropTypes from 'prop-types';
|
|
5
5
|
import { SmartImage } from '../cms/smartimage';
|
|
6
6
|
import { usePixelatedConfig } from '../config/config.client';
|
|
7
7
|
import { DragHandler } from './carousel.drag';
|
|
@@ -11,11 +11,22 @@ function capitalize(str) {
|
|
|
11
11
|
}
|
|
12
12
|
/* ========== CAROUSEL ========== */
|
|
13
13
|
Carousel.propTypes = {
|
|
14
|
-
cards: PropTypes.
|
|
14
|
+
cards: PropTypes.arrayOf(PropTypes.shape({
|
|
15
|
+
index: PropTypes.number.isRequired,
|
|
16
|
+
cardIndex: PropTypes.number.isRequired,
|
|
17
|
+
cardLength: PropTypes.number.isRequired,
|
|
18
|
+
link: PropTypes.string,
|
|
19
|
+
linkTarget: PropTypes.string,
|
|
20
|
+
image: PropTypes.string.isRequired,
|
|
21
|
+
imageAlt: PropTypes.string,
|
|
22
|
+
imgFit: PropTypes.oneOf(['contain', 'cover', 'fill']),
|
|
23
|
+
headerText: PropTypes.string,
|
|
24
|
+
subHeaderText: PropTypes.string,
|
|
25
|
+
bodyText: PropTypes.string,
|
|
26
|
+
})).isRequired,
|
|
15
27
|
draggable: PropTypes.bool,
|
|
16
28
|
imgFit: PropTypes.oneOf(['contain', 'cover', 'fill'])
|
|
17
29
|
};
|
|
18
|
-
// export type CarouselType = InferProps<typeof Carousel.propTypes>;
|
|
19
30
|
export function Carousel(props) {
|
|
20
31
|
const debug = false;
|
|
21
32
|
let timer = useRef(null);
|
|
@@ -74,7 +85,7 @@ export function Carousel(props) {
|
|
|
74
85
|
console.log('CarouselSimple: Dragging disabled');
|
|
75
86
|
}
|
|
76
87
|
if (props.cards && props.cards.length > 0) {
|
|
77
|
-
return (_jsxs("div", { className: "carousel-container", children: [_jsx("div", { className: "carousel-cards-container", children: props.cards.map((card, i) => (_jsx(CarouselCard, { index: i, cardIndex: cardIndex, cardLength: props.cards.length, link: card.link, linkTarget: card.linkTarget || '_self', image: card.image, imageAlt: card.imageAlt, imgFit: props.imgFit
|
|
88
|
+
return (_jsxs("div", { className: "carousel-container", children: [_jsx("div", { className: "carousel-cards-container", children: props.cards.map((card, i) => (_jsx(CarouselCard, { index: i, cardIndex: cardIndex, cardLength: props.cards.length, link: card.link, linkTarget: card.linkTarget || '_self', image: card.image, imageAlt: card.imageAlt, imgFit: (props.imgFit || 'fill'), headerText: card.headerText, subHeaderText: card.subHeaderText, bodyText: card.bodyText }, i))) }), _jsxs("div", { className: "carousel-buttons", children: [_jsx(CarouselButton, { clickFunction: previousCard, glyph: '\u25C0' }), _jsx(CarouselButton, { clickFunction: stopTimer, glyph: '\u23F8' }), _jsx(CarouselButton, { clickFunction: nextCard, glyph: '\u25B6' })] })] }));
|
|
78
89
|
}
|
|
79
90
|
else {
|
|
80
91
|
return (_jsx("div", { className: 'section-container', children: _jsx("div", { className: "carousel-container", children: _jsx(CarouselLoading, {}) }) }));
|
|
@@ -7,7 +7,7 @@ import { usePixelatedConfig } from '../config/config.client';
|
|
|
7
7
|
import "../../css/pixelated.grid.scss";
|
|
8
8
|
import "./tiles.css";
|
|
9
9
|
Tiles.propTypes = {
|
|
10
|
-
cards: PropTypes.
|
|
10
|
+
cards: PropTypes.array.isRequired,
|
|
11
11
|
rowCount: PropTypes.number,
|
|
12
12
|
};
|
|
13
13
|
export function Tiles(props) {
|
|
@@ -5,7 +5,7 @@ import PropTypes from "prop-types";
|
|
|
5
5
|
import { Carousel } from '../carousel/carousel';
|
|
6
6
|
import { getContentfulEntriesByType, getContentfulEntryByEntryID } from "./contentful.delivery";
|
|
7
7
|
import { usePixelatedConfig } from '../config/config.client';
|
|
8
|
-
import {
|
|
8
|
+
import { addToShoppingCart } from "../shoppingcart/shoppingcart.functions";
|
|
9
9
|
import { AddToCartButton, /* GoToCartButton */ ViewItemDetails } from "../shoppingcart/shoppingcart.components";
|
|
10
10
|
import { getCloudinaryRemoteFetchURL as getImg } from "./cloudinary";
|
|
11
11
|
// import { Loading, ToggleLoading } from "../general/pixelated.loading";
|
|
@@ -135,7 +135,7 @@ export function ContentfulListItem(props) {
|
|
|
135
135
|
? _jsx(ContentfulItemHeader, { url: itemURL, target: itemURLTarget, title: thisItem.fields.title })
|
|
136
136
|
: _jsx(ContentfulItemHeader, { title: thisItem.fields.title }) }), _jsxs("div", { className: "contentful-item-details grid12", children: [_jsxs("div", { children: [_jsx("b", { children: "Item ID: " }), thisItem.sys.id] }), _jsxs("div", { children: [_jsx("b", { children: "UPC ID: " }), thisItem.fields.id] }), _jsxs("div", { children: [_jsx("b", { children: "Quantity: " }), thisItem.fields.quantity] }), _jsxs("div", { children: [_jsx("b", { children: "Brand / Model: " }), thisItem.fields.brand, " ", thisItem.fields.model] }), _jsxs("div", { children: [_jsx("b", { children: "Listing Date: " }), thisItem.fields.date] })] }), _jsx("div", { className: "contentful-item-price", children: itemURL
|
|
137
137
|
? _jsxs("a", { href: itemURL, target: itemURLTarget, rel: "noreferrer", children: ["$", thisItem.fields.price, " USD"] })
|
|
138
|
-
: "$" + thisItem.fields.price + " USD" }), _jsx("br", {}), _jsxs("div", { className: "contentful-item-addtocart", children: [_jsx(ViewItemDetails, { href: "/store", itemID: thisItem.sys.id }), _jsx(AddToCartButton, { handler:
|
|
138
|
+
: "$" + thisItem.fields.price + " USD" }), _jsx("br", {}), _jsxs("div", { className: "contentful-item-addtocart", children: [_jsx(ViewItemDetails, { href: "/store", itemID: thisItem.sys.id }), _jsx(AddToCartButton, { handler: addToShoppingCart, item: shoppingCartItem, itemID: thisItem.sys.id })] })] })] }));
|
|
139
139
|
}
|
|
140
140
|
/* ========== CONTENTFUL ITEM HEADER ========== */
|
|
141
141
|
ContentfulItemHeader.propTypes = {
|
|
@@ -156,7 +156,6 @@ ContentfulItemDetail.propTypes = {
|
|
|
156
156
|
};
|
|
157
157
|
export function ContentfulItemDetail(props) {
|
|
158
158
|
const [item, setItem] = useState({});
|
|
159
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
160
159
|
const [assets, setAssets] = useState({});
|
|
161
160
|
const [cards, setCards] = useState([]);
|
|
162
161
|
const providerContentfulApiProps = usePixelatedConfig()?.contentful;
|
|
@@ -235,7 +234,7 @@ export function ContentfulItemDetail(props) {
|
|
|
235
234
|
? _jsx(ContentfulItemHeader, { url: itemURL, title: thisItem.fields.title })
|
|
236
235
|
: _jsx(ContentfulItemHeader, { title: thisItem.fields.title }) }), _jsx("br", {}), _jsx("div", { className: "contentful-item-photo-carousel grid-s1-e7", children: _jsx(Carousel, { cards: cards, draggable: true, imgFit: "contain" }) }), _jsxs("div", { className: "grid-s7-e13", children: [_jsx("div", { className: "contentful-item-details grid12", children: _jsx("div", { dangerouslySetInnerHTML: { __html: thisItem.fields.description.replace(/(<br\s*\/?>\s*){2,}/gi, '') } }) }), _jsx("br", {}), _jsxs("div", { className: "contentful-item-details grid12", children: [_jsxs("div", { children: [_jsx("b", { children: "Item ID: " }), thisItem.sys.id] }), _jsxs("div", { children: [_jsx("b", { children: "UPC ID: " }), thisItem.fields.id] }), _jsxs("div", { children: [_jsx("b", { children: "Quantity: " }), thisItem.fields.quantity] }), _jsxs("div", { children: [_jsx("b", { children: "Brand / Model: " }), thisItem.fields.brand, " ", thisItem.fields.model] }), _jsxs("div", { children: [_jsx("b", { children: "Listing Date: " }), thisItem.fields.date] }), _jsx("br", {})] }), _jsx("div", { className: "contentful-item-price", children: itemURL
|
|
237
236
|
? _jsxs("a", { href: itemURL, target: itemURLTarget, rel: "noreferrer", children: ["$", thisItem.fields.price, " USD"] })
|
|
238
|
-
: "$" + thisItem.fields.price + " USD" }), _jsx("br", {}), _jsx("div", { className: "contentful-item-addtocart", children: _jsx(AddToCartButton, { handler:
|
|
237
|
+
: "$" + thisItem.fields.price + " USD" }), _jsx("br", {}), _jsx("div", { className: "contentful-item-addtocart", children: _jsx(AddToCartButton, { handler: addToShoppingCart, item: shoppingCartItem, itemID: thisItem.sys.id }) })] })] }) }));
|
|
239
238
|
}
|
|
240
239
|
else {
|
|
241
240
|
return (_jsx(_Fragment, { children: _jsx("div", { id: "contentful-items", className: "contentful-items", children: _jsx("div", { className: "centered", children: "Loading..." }) }) }));
|
|
@@ -22,9 +22,9 @@ export function GoogleReviewsCard(props) {
|
|
|
22
22
|
try {
|
|
23
23
|
const result = await getGoogleReviewsByPlaceId({
|
|
24
24
|
placeId: props.placeId,
|
|
25
|
-
language: props.language,
|
|
26
|
-
maxReviews: props.maxReviews,
|
|
27
|
-
proxyBase: props.proxyBase,
|
|
25
|
+
language: props.language ?? undefined,
|
|
26
|
+
maxReviews: props.maxReviews ?? undefined,
|
|
27
|
+
proxyBase: props.proxyBase ?? undefined,
|
|
28
28
|
apiKey: props.apiKey || GOOGLE_MAPS_API_KEY,
|
|
29
29
|
});
|
|
30
30
|
setPlace(result.place);
|