diff --git a/src/components/PackImg.js b/src/components/PackImg.js
index f38937be4..ea6b43e20 100644
--- a/src/components/PackImg.js
+++ b/src/components/PackImg.js
@@ -1,13 +1,23 @@
-import React from 'react';
+import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { css } from '@emotion/react';
import DEFAULT_IMAGE from '../images/default-logo-background.svg';
-const createPackAcronym = (name) =>
- name.split(' ').reduce((acc, word) => `${acc}${word.charAt(0)}`, '');
-
const PackImg = ({ className, logoUrl, packName }) => {
- const packAcronym = createPackAcronym(packName);
+ const [packAcronym, setPackAcronym] = useState('');
+
+ const getPackNameAcronym = () => {
+ let packNameAcronym = '';
+ packName.split(' ').forEach((word) => {
+ packNameAcronym = packNameAcronym.concat('', word.charAt(0));
+ });
+ setPackAcronym(packNameAcronym.toUpperCase());
+ };
+ useEffect(() => {
+ if (!logoUrl) {
+ getPackNameAcronym();
+ }
+ });
if (logoUrl) {
return (
@@ -41,7 +51,7 @@ const PackImg = ({ className, logoUrl, packName }) => {
align-items: center;
`}
>
-
{packAcronym.toUpperCase()}
+ {packAcronym}
);
};
diff --git a/src/components/PackTile.js b/src/components/PackTile.js
index d2f504b12..2b8535af9 100644
--- a/src/components/PackTile.js
+++ b/src/components/PackTile.js
@@ -10,15 +10,15 @@ import {
useInstrumentedHandler,
} from '@newrelic/gatsby-theme-newrelic';
import PackImg from './PackImg';
-import {
- QUICKSTART_SUPPORT_LEVELS,
- QUICKSTART_CATALOG_VIEWS,
-} from '../data/constants';
-const SHIELD_LEVELS = [
- QUICKSTART_SUPPORT_LEVELS.NEWRELIC,
- QUICKSTART_SUPPORT_LEVELS.VERIFIED,
-];
+const LEVELS = {
+ NEWRELIC: 'NEWRELIC',
+};
+
+const VIEWS = {
+ GRID: 'Grid view',
+ LIST: 'List view',
+};
const PackTile = ({
id,
@@ -70,7 +70,7 @@ const PackTile = ({
css={css`
overflow: hidden;
- ${view === QUICKSTART_CATALOG_VIEWS.LIST &&
+ ${view === VIEWS.LIST &&
css`
display: flex;
margin-bottom: 1em;
@@ -85,11 +85,11 @@ const PackTile = ({
height: 200px;
background-color: var(--color-white);
object-fit: scale-down;
- width: ${view === QUICKSTART_CATALOG_VIEWS.GRID ? 100 : 25}%;
- padding: 0 ${view === QUICKSTART_CATALOG_VIEWS.GRID ? 5 : 1}%;
- margin: ${view === QUICKSTART_CATALOG_VIEWS.GRID ? 'auto' : 0};
+ width: ${view === VIEWS.GRID ? 100 : 25}%;
+ padding: 0 ${view === VIEWS.GRID ? 5 : 1}%;
+ margin: ${view === VIEWS.GRID ? 'auto' : 0};
- ${view === QUICKSTART_CATALOG_VIEWS.LIST &&
+ ${view === VIEWS.LIST &&
css`
max-height: 150px;
@@ -103,7 +103,7 @@ const PackTile = ({
css={css`
padding: 1em;
- ${view === QUICKSTART_CATALOG_VIEWS.LIST &&
+ ${view === VIEWS.LIST &&
css`
width: 75%;
@@ -114,8 +114,7 @@ const PackTile = ({
`}
>
- {name}{' '}
- {SHIELD_LEVELS.includes(level) && }
+ {name} {level === LEVELS.NEWRELIC && }
{
- return (
- <>
-
- Showing {quickstarts.length} results
-
-
-
-
-
- {quickstarts.map((pack) => (
-
- ))}
-
- >
- );
-};
-
-QuickstartGridList.propTypes = {
- quickstarts: PropTypes.arrayOf(quickstart).isRequired,
- view: PropTypes.oneOf(Object.values(QUICKSTART_CATALOG_VIEWS)),
-};
-
-export default QuickstartGridList;
diff --git a/src/data/constants.js b/src/data/constants.js
index 3a77be2a7..0637044b5 100644
--- a/src/data/constants.js
+++ b/src/data/constants.js
@@ -49,11 +49,6 @@ export const QUICKSTART_ALERT_TYPES = {
STATIC: 'STATIC',
};
-export const QUICKSTART_CATALOG_VIEWS = {
- GRID: 'GRID',
- LIST: 'LIST',
-};
-
export const QUICKSTARTS_REPO =
'https://github.com/newrelic/newrelic-observability-packs';
diff --git a/src/pages/instant-observability.js b/src/pages/instant-observability.js
index 8ef68abb5..fd819a595 100644
--- a/src/pages/instant-observability.js
+++ b/src/pages/instant-observability.js
@@ -2,135 +2,118 @@ import PropTypes from 'prop-types';
import { graphql } from 'gatsby';
import React, { useState, useEffect } from 'react';
import useMobileDetect from 'use-mobile-detect-hook';
-import { useQueryParams, StringParam } from 'use-query-params';
import DevSiteSeo from '../components/DevSiteSeo';
import { css } from '@emotion/react';
import SegmentedControl from '../components/SegmentedControl';
-import QuickstartGridList from '../components/quickstarts/QuickstartGridList';
-import { QUICKSTART_CATALOG_VIEWS } from '../data/constants';
-import MobileQSFilter from '../components/MobileQSFilter';
+import PackTile from '../components/PackTile';
+import Select from '../components/Select';
import {
SearchInput,
useTessen,
+ ExternalLink,
Button,
Icon,
} from '@newrelic/gatsby-theme-newrelic';
-import { useDebounce } from 'react-use';
+import { navigate } from '@reach/router';
+import BUILD_YOUR_OWN from '../images/build-your-own.svg';
import { useDebounce } from 'react-use';
-import { useQueryParams, StringParam } from 'use-query-params';
-
-const VIEWS = [
- {
- label: 'Grid view',
- value: QUICKSTART_CATALOG_VIEWS.GRID,
- },
- {
- label: 'List view',
- value: QUICKSTART_CATALOG_VIEWS.LIST,
- },
+
+const { QUICKSTARTS_REPO } = require('../data/constants');
+
+const FILTERS = [
+ { name: 'All', type: '', icon: 'nr-all-entities' },
+ { name: 'Dashboards', type: 'dashboards', icon: 'nr-dashboard' },
+ { name: 'Alerts', type: 'alerts', icon: 'nr-alert' },
+ { name: 'Data sources', type: 'documentation', icon: 'nr-document' },
];
-const prop = (key) => (obj) => obj[key];
-const withComponent = (packs, key) => packs.filter((p) => p[key].length > 0);
+const VIEWS = {
+ GRID: 'Grid view',
+ LIST: 'List view',
+};
+
+/**
+ * Filters a quickstart based on a provided search term.
+ * @param {String} search Search term.
+ * @returns {(Object) => Boolean} Callback function to be used by filter.
+ */
+const filterBySearch = (search) => ({ name, description }) => {
+ return (
+ !search ||
+ name.toLowerCase().includes(search.toLowerCase()) ||
+ description.toLowerCase().includes(search.toLowerCase())
+ );
+};
+
+/**
+ * Filters a quickstart based on a content type.
+ * @param {String} type The content type (e.g. 'alerts').
+ * @returns {(Object) => Boolean} Callback function to be used by filter.
+ */
+const filterByContentType = (type) => (quickstart) => {
+ return !type || (quickstart[type] && quickstart[type].length > 0);
+};
const QuickstartsPage = ({ data, location }) => {
- const tessen = useTessen();
+ const [view, setView] = useState(VIEWS.GRID);
const detectMobile = useMobileDetect();
- const isMobile = detectMobile.isMobile();
+ const tessen = useTessen();
- const [isClient, setClient] = useState(false);
+ const [search, setSearch] = useState('');
+ const [filter, setFilter] = useState('');
useEffect(() => {
- setClient(true);
- }, []);
+ const params = new URLSearchParams(location.search);
+ const searchParam = params.get('search');
+ const filterParam = params.get('filter');
+ setSearch(searchParam);
+ setFilter(filterParam);
+ }, [location.search]);
- const {
- allQuickstarts: { nodes: quickstarts },
- } = data;
+ const handleFilter = (value) => {
+ setFilter(value);
+ const params = new URLSearchParams(location.search);
+ params.set('filter', value);
+ navigate(`?${params.toString()}`);
+ };
+
+ const handleSearch = (value) => {
+ if (value !== null && value !== undefined) {
+ const params = new URLSearchParams(location.search);
+ params.set('search', value);
+
+ navigate(`?${params.toString()}`);
+ }
+ };
- const [view, setView] = useState(QUICKSTART_CATALOG_VIEWS.GRID);
- useEffect(() => {
- setView(view);
- }, [view]);
-
- const [queryParams, setQueryParams] = useQueryParams({
- search: StringParam,
- filter: StringParam,
- });
- const [formState, setFormState] = useState({
- search: queryParams.search || '',
- filter: queryParams.filter || '',
- });
-
- // This is purely to prevent sending incomplete search events
- // to tessen
useDebounce(
() => {
- if (formState.search && formState.search !== '') {
- tessen.track('observabilityPack', `packSearch`, {
- packSearchTerm: formState.search,
- });
- if (typeof window !== 'undefined' && window.newrelic) {
- window.newrelic.addPageAction('packSearch', {
- packSearchTerm: formState.search,
- });
- }
- }
+ handleSearch(search);
},
- 1000,
- [formState]
+ 400,
+ [search]
);
- // Updates the url based on the current form state
- useEffect(() => {
- setQueryParams(formState, 'replace');
- }, [formState, setQueryParams]);
+ const quickstarts = data.allQuickstarts.nodes;
- let filteredPacks = quickstarts.filter(
- (qs) =>
- qs.name.toLowerCase().includes(formState.search.toLowerCase()) ||
- qs.description.toLowerCase().includes(formState.search.toLowerCase())
- );
+ const filteredQuickstarts = quickstarts
+ .filter(filterBySearch(search))
+ .filter(filterByContentType(filter));
- // This array is used to populate filters with a name, value,
- // and count of packs within each filter
- const packContentsFilterValues = [
- {
- filterName: 'All',
- filterValue: 'all',
- filterCount: filteredPacks.length,
- iconName: 'nr-all-entities',
- },
- {
- filterName: 'Dashboards',
- filterValue: 'dashboards',
- filterCount: withComponent(filteredPacks, 'dashboards').length,
- iconName: 'nr-dashboard',
- },
- {
- filterName: 'Alerts',
- filterValue: 'alerts',
- filterCount: withComponent(filteredPacks, 'alerts').length,
- iconName: 'nr-alerts',
- },
- {
- filterName: 'Data sources',
- filterValue: 'documentation',
- filterCount: withComponent(filteredPacks, 'documentation').length,
- iconName: 'nr-document',
- },
- ];
-
- if (
- formState.filter !== 'all' &&
- packContentsFilterValues.map(prop('filterValue')).includes(formState.filter)
- ) {
- filteredPacks = withComponent(filteredPacks, formState.filter);
- }
+ const filtersWithCount = FILTERS.map((filter) => ({
+ ...filter,
+ count: quickstarts
+ .filter(filterBySearch(search))
+ .filter(filterByContentType(filter.type)).length,
+ }));
return (
<>
-
+
{
`}
/>
- //START my code
- {/* */}
- {/* */}
- // END my code // START LIZ CODE
-
- {isMobile ? (
-
+
+ {detectMobile.isMobile() ? (
+
) : (
- packContentsFilterValues.map(
- ({ filterName, filterValue, filterCount, iconName }, i) => (
-
+ ))
)}
- // END LIZ CODE
@@ -274,6 +235,7 @@ const QuickstartsPage = ({ data, location }) => {
{
{
>
{
- setFormState({ ...formState, search: '' });
- }}
+ value={search}
+ placeholder="Search pack names / descriptions"
+ onClear={() => setSearch('')}
onChange={(e) => {
- setFormState({ ...formState, search: e.target.value });
+ const value = e.target.value;
+ setSearch(value);
}}
/>
@@ -326,11 +288,11 @@ const QuickstartsPage = ({ data, location }) => {
css={css`
display: inline-block;
min-width: 155px;
- margin-left: 1rem;
+ margin-left: 20px;
`}
>
{
setView(view);
@@ -342,11 +304,57 @@ const QuickstartsPage = ({ data, location }) => {
- {isClient ? (
-
- ) : (
-
- )}
+
+ Showing {filteredQuickstarts.length} results
+
+
+
+
+
+ {filteredQuickstarts.map((pack) => (
+
+ ))}
+
>
@@ -372,20 +380,10 @@ export const pageQuery = graphql`
packUrl
level
dashboards {
- name
- url
description
- }
- alerts {
name
- details
+ screenshots
url
- type
- }
- documentation {
- name
- url
- description
}
alerts {
details