Skip to content
This repository has been archived by the owner on Dec 8, 2023. It is now read-only.

Commit

Permalink
feat: shadow theme's 404 page
Browse files Browse the repository at this point in the history
* Shadow the theme's 404 page
* Reduce functionality to just show the top 5 results for a particular url
  • Loading branch information
aswanson-nr committed Jul 18, 2022
1 parent a179b61 commit 1a4b2aa
Showing 1 changed file with 207 additions and 0 deletions.
207 changes: 207 additions & 0 deletions src/@newrelic/gatsby-theme-newrelic/pages/404.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
import React, { useEffect, useState, useCallback } from 'react';
import PropTypes from 'prop-types';
import { css } from '@emotion/react';

import {
useTessen,
Button,
CreateIssueButton,
Tag,
Link,
} from '@newrelic/gatsby-theme-newrelic';

import QuickstartLayout from '../../../layouts/QuickStartLayout';

const NotFoundPage = ({ location, pageContext: { swiftypeEngineKey } }) => {
const [searchTerm, setSearchTerm] = useState(null);
const [searchResult, setSearchResult] = useState(null);
const tessen = useTessen();

const getSearchResults = useCallback(async () => {
const search = async () => {
const res = await fetch(
'https://search-api.swiftype.com/api/v1/public/engines/search.json',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
q: searchTerm,
engine_key: swiftypeEngineKey,
per_page: 5,
filters: {
page: {
type: [`docs`, `developers`, `opensource`, `quickstarts`],
document_type: [
'!views_page_menu',
'!term_page_api_menu',
'!term_page_landing_page',
],
},
},
}),
}
);

const { records } = await res.json();

return records.page;
};

if (searchTerm !== null) {
const results = await search();
const trimmedResults = results.map((r) => {
return { url: r.url, title: r.title, type: r.type };
});

setSearchResult(trimmedResults);
}
}, [searchTerm, swiftypeEngineKey]);

useEffect(() => {
setSearchTerm(location.pathname.split('/').join(' '));
}, [location.pathname]);

useEffect(() => {
getSearchResults();
}, [getSearchResults, searchTerm]);

useEffect(() => {
if (searchResult) {
tessen.track({
eventName: 'error404',
category: 'ErrorPage',
path: location.pathname,
resultCount: searchResult.length,
searchTerm,
});
}
}, [location.pathname, searchResult, searchTerm, tessen]);

return (
<QuickstartLayout>
<div
css={css`
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: auto;
grid-template-areas:
'. . . .'
'. content content .'
'footer footer footer footer';
min-height: calc(100vh - var(--global-header-height));
max-height: calc(100vh - var(--global-header-height));
`}
>
<div
css={css`
display: flex;
grid-area: content;
justify-self: start;
`}
>
<div
css={css`
font-size: 0.85rem;
`}
>
<h1
css={css`
font-weight: normal;
line-height: 1;
`}
>
Hmm... We can't find this
</h1>
<div
css={css`
> * {
margin-top: 3em;
}
`}
>
{displaySearchResults(searchTerm, searchResult)}
<p>
Find more in the{' '}
<Link to="/">Instant Observability catalogue</Link> or{' '}
<CreateIssueButton
pageTitle="404"
variant={Button.VARIANT.OUTLINE}
size={Button.SIZE.SMALL}
labels={['bug', '404']}
instrumentation={{ component: '404Page' }}
/>
</p>
</div>
</div>
</div>
</div>
</QuickstartLayout>
);
};

NotFoundPage.propTypes = {
location: PropTypes.shape({
href: PropTypes.string.isRequired,
origin: PropTypes.string.isRequired,
pathname: PropTypes.string.isRequired,
}).isRequired,
pageContext: PropTypes.shape({
themeOptions: PropTypes.object.isRequired,
swiftypeEngineKey: PropTypes.string.isRequired,
}).isRequired,
};

const displaySearchResults = (term, results) => {
if (!results || results.length === 0) {
return null;
}

return (
<div id="search-results">
Were you looking for any of these?
<ul
css={css`
list-style-type: none;
padding: 0;
line-height: 1.75rem;
margin: 1rem 0 0;
`}
>
{results.map((result, index) => {
return (
<li key={`result-${index}`}>
<div>
<Link
to={result.url}
css={css`
text-decoration: none;
`}
instrumentation={{
component: '404SuggestedLink',
href: result.url,
term,
}}
displayExternalIcon
>
{result.title}
</Link>
</div>
<Tag
css={css`
font-size: 0.625rem;
margin-right: 0.5em;
`}
uppercase
>
{result.type?.replace('_', ' ')}
</Tag>
</li>
);
})}
</ul>
</div>
);
};
export default NotFoundPage;

0 comments on commit 1a4b2aa

Please sign in to comment.